【问题标题】:OpenCV trackbar callback in C++ classC++ 类中的 OpenCV 轨迹栏回调
【发布时间】:2011-12-26 14:37:37
【问题描述】:

我有一个问题,关于在使用 C++ 中的类时如何在 OpenCV 中定义轨迹栏的回调。

当我在我的 .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...我猜这是范围的问题。但是不知道怎么解决?

任何帮助将不胜感激。

非常感谢。

【问题讨论】:

    标签: c++ opencv callback trackbar


    【解决方案1】:

    回调函数必须是静态的或全局的,但您可以将引用传递给您想要操作的对象(请参阅 OpenCV 用户邮件列表中的 this post)。

    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.
    }
    

    请注意,您不需要自己显式更新变量,只要您在创建轨迹栏时提供了指向它的指针(如上),但如果您需要先处理它,我建议您在回调函数。

    【讨论】:

      【解决方案2】:

      您必须将回调函数实现为全局函数或静态成员函数。为了让它看起来更像 OOP,你可能更喜欢将它实现为静态成员函数:)

      【讨论】:

      • 我刚刚尝试过,它适用于全局函数,但仅适用于方法 cvCreateTrackBar 而不是 createTrackBar。我并没有放弃这两者之间的区别,但它现在有效。
      • 你知道为什么它必须是全局的还是静态的?如果它是成员函数(除了给出编译错误)会有什么问题。
      • @user2565010,这是因为调用成员函数时,调用中包含了一个隐藏参数(即您的类的“this”指针)。在全局/静态成员函数中,this 指针不作为参数传递。
      【解决方案3】:

      我正在使用不同的解决方案来获取类变量中的滑块值(在我的情况下,获取实时视频流的选定旋转角度)。 createTrackbar 函数中的int* value 是一个公共类变量,然后在循环中使用它(在获取视频时,但这可能会导致重复重绘单个图像的混乱工作)。

      不是最好的解决方案,但对我有用。

      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;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多