Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

How to create a class for trackbars in general?

I would like to create a general Trackbar class what I would like to use with different functions. The maximum number of trackbar I need is 3. It should be flexible: sometimes I would use 1 trackbar for 2 images (for xample blend to image in different ratios), sometimes I would like to use 3 trackbar for one image (eg: set RGB paramaters for an image). My idea was to crate a Trackbar class. It has a constructor which takes all the neccessary parameter to create + it takes a function pointer, a vector of Mat pointer (the input images), and a vector of integers (the values I should modify), and the number of trackbar I use.

Trackbar(int value, int maxValue, std::string trackbarName, std::string windowName, cv::Mat* (*func_ptr)(std::vector<cv::Mat*> images, std::vector<int> values), std::vector<cv::Mat*> imagesInput, std::vector<int> values, int trackbarSelect)

The constructor creates a trackbar with a callback (out of the predefined 3) based on which is the trackbarSelect.

if (trackbarSelect == 0) {
        cv::createTrackbar(_trackbarName, _windowName, &_startValue, _maxValue, trackbarCallback);
        trackbarCallback(_values.at(trackbarSelect), 0);
    } else if (trackbarSelect == 1) {
        cv::createTrackbar(_trackbarName, _windowName, &_startValue, _maxValue, trackbarCallback2);
        trackbarCallback2(_values.at(trackbarSelect), 0);
    }  else if (trackbarSelect == 2) {
        cv::createTrackbar(_trackbarName, _windowName, &_startValue, _maxValue, trackbarCallback2);
        trackbarCallback3(_values.at(trackbarSelect), 0); }

}

The callbacs calls the pointed function which is written in general form: it could handle multiple images if needed (since the first parameter is a vector) and could handle multiple values if needed because the second parameter is a vector too. It returns with a Mat pointer which will be displayed in the callback.

void Trackbar::trackbarCallback( int, void* )
{
    _values.at(trackbarSelect) = cv::getTrackbarPos(_trackbarName, _windowName);
    cv::Mat* result = _func_ptr(_imagesInput, _values);
    cv::imshow(_windowName, *result);
}

An example function I would like to handle with this:

cv::Mat* rgbFunction(std::vector<cv::Mat*> images, std::vector<int> values)
{
    *images[0] = cv::Scalar(values.at(0), values.at(1), values.at(2));
    return images.at(0);
}

void colorSetter(void)
{
    cv::Mat img(1000, 1000, CV_8UC3, cv::Scalar(0, 0, 0));
    std::vector<cv::Mat*> images;
    images.push_back(&img);
    std::vector<int> values = {0, 0, 0};

    std::string windowname = "RGB_Sliders";
    cv::namedWindow(windowname, cv::WINDOW_AUTOSIZE);

    Trackbar blueTrackbar(0, 100, "blue", windowname, &rgbFunction, images, values, 0);
    Trackbar greenTrackbar(0, 100, "green", windowname, &rgbFunction, images, values, 1);
    Trackbar redTrackbar(0, 100, "red", windowname, &rgbFunction, images, values, 2);

    cv::waitKey(0);
    cv::destroyWindow(windowname);
}

My problem is that I have a strong feeling that I overcomplicated things here and this could be done much easier if I have a better understanding + this isn't work perfectly well for some reason. I little help would be much appreciated - please be very clear since I just start to learn OpenCV a week ago! Thank you very much in advance!