Обратный вызов трекбара OpenCV в классе C ++ - PullRequest
3 голосов
/ 26 декабря 2011

У меня есть вопрос о том, как определить обратный вызов для трекбаров в OpenCV при работе с классами в C ++.

Когда я определяю свой трекбар, скажем в методе конструктора моего класса .cpp, как я могу определитьобратный вызов?

Я пытался работать с указателями на функции, но это не сработало.Наверное, я что-то делаю очень неправильно: -)

Это мой заголовочный файл:

class SliderwithImage {

public:
    SliderwithImage(void);
    ~SliderwithImage(void); 

    void sliderCallBack(int pos);
};

Это файл реализации:

#include "SliderwithImage.h"

void SliderwithImage::sliderCallBack(int pos) {


}

SliderwithImage::SliderwithImage(void)  {

    const char* windowName = "window";
    int lowvalue  =1;

    namedWindow(windowName,  CV_GUI_EXPANDED);

    createTrackbar("mytrackbar", windowName, &lowvalue, 255, sliderCallBack);

}

SliderwithImage::~SliderwithImage(void) {

}

Очевидно, чтоМетод createTrackbar не распознает sliderCallBack ... Я думаю, это проблема области видимости.Но я не уверен, как решить эту проблему?

Любая помощь будет оценена.

Большое спасибо.

Ответы [ 3 ]

6 голосов
/ 10 мая 2012

Функция обратного вызова должна быть статической или глобальной, но вы можете передать ей ссылку на объект, с которым хотите работать (см. это сообщение в списке рассылки OpenCV Users).

Метод createTrackbar имеет параметр userdata, который передается вызывающей функции.В C есть недокументированный метод cvCreateTrackbar2, определенный в highgui_c.h, который имеет ту же функциональность:

CVAPI(int) cvCreateTrackbar2( const char* trackbar_name, const char* window_name,
    int* value, int count, CvTrackbarCallback2 on_change,
    void* userdata CV_DEFAULT(0));

Эти методы позволяют вам создать класс со статической функцией обратного вызова, которая принимает указатель наобъект этого класса.Вы можете создать трекбар следующим образом:

cv:createTrackbar("Label", "Window" &variable, MAX_VAL, &MyClass::func, this);

Обратный вызов будет выглядеть примерно так:

void MyClass:func(int newValue, void * object) {
    MyClass* myClass = (MyClass*) object;
    // ...do stuff.
}

Обратите внимание, что вам не нужно явно обновлять переменную самостоятельно, покавы указали на него указатель при создании трекбара (как указано выше), но если вам нужно сначала обработать его, я предлагаю вам установить его явно в функции обратного вызова.

3 голосов
/ 26 декабря 2011

Вы должны реализовать функцию обратного вызова в виде глобальной функции или статической функции-члена. Чтобы он выглядел более ООП, вы можете предпочесть реализовать его как статическую функцию-член

0 голосов
/ 17 января 2013

Я использую другое решение для получения значения ползунка в переменной класса (в моем случае для получения выбранного угла поворота живого видеопотока). int* value в функции createTrackbar - это переменная открытого класса, которая затем используется в цикле (при получении видео, но это может беспорядочно работать многократно перерисовывая одно изображение).

Не лучшее решение, но оно работает для меня.

cv::createTrackbar("Rotation Angle(deg)", "Preview", &rotationAngle, 
alpha_slider_max, NULL);

    for(;;)
    {
        int rotAngle = this -> rotationAngle;
        cv::Mat frame;
        cv::Mat rot_frame;
        this -> capture >> frame;
        rot_frame = rotateVideo (frame, rotAngle);  
        imshow("Preview", rot_frame);
        if(cv::waitKey(30) >= 0) break;
    }
...