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!
YAGNI
it also expects a global, static callback , not a class member function
@berak Thank you for your answer but I do not understand it completely yet. Could you please show me some minimal code of how to implement this general purpose trackbar class?
goto line 1
btw, NEVER save or pass pointers to cv::Mat, you'll wreck havoc with the refcounts. (it's a "smart pointer" already !)