在使用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 ......我猜这是范围问题。但我不确定如何解决这个问题?
任何帮助都将不胜感激。
非常感谢。
答案 0 :(得分:5)
回调函数必须是静态的或全局的,但您可以向其传递对要操作的对象的引用(请参阅OpenCV Users邮件列表上的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.
}
请注意,只要在创建轨迹栏时提供指向它的指针(如上所述),就不需要自己显式更新变量,但如果您需要先处理它,我建议您在回调函数。
答案 1 :(得分:3)
您必须将回调函数实现为全局函数或静态成员函数。为了使其更具OOP外观,您可能更愿意将其实现为静态成员函数:)
答案 2 :(得分:0)
我使用不同的解决方案来获取类变量中的滑块值(在我的情况下,获取实时视频流的选定旋转角度)。 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;
}