最近写一个程序,希望与用户之间的交互功能比较具有亲和力。其中用到了鼠标事件,对于鼠标事件,Intel 算机视觉库 (OpenCV) 中对鼠标事件的响应采用回调函数的方式来处理。即,为了可以响应鼠标点击事件,首先必须创建一个回调函数,使鼠标点击事件发生时 OpenCV 可以调用这个函数。创建这个函数以后,需要在 OpenCV 中注册这个函数,以便特定窗口被触发鼠标事件以后,OpenCV 可以正确调用这个函数。
回调函数 callback 可以是满足指定输入参数以及返回参数类型的任何参数。这里,我们必须清楚告诉回调函数触发的事件以及触发位置。函数还需要被告知,用户是够在触发鼠标事件时同时触发了 Shift 或者 Alt等键,下面是回调函数必须符合的格式:
void CvMouseCallback (int event, int x, int y, int flags, void* pram);
现在,当回调函数被调用,OpenCV会给函数传入合适的值。第一个参数 event 必须为鼠标事件类型值中的一个,如 CV_EVENT_LBUTTONDOWN。其他参数的说明参见《学习OpenCV(中文版)》便可知晓,这里重点介绍使用过程中可能遇到的一些问题 ——如何将自定义CvMouseCallback声明为类成员函数(只能是静态 static的),并且访问类的非静态成员变量。
通常情况下,由于我们会采用面向对象的程序设计方法来设计我们的程序 (比如C++),但是根据OpenCV的文档CVAPI: (void) cvSetMouseCallback(const char* window_name, CvMouseCallback on_mouse, void* param CV_DEFAULT(NULL)); cvSetMouseCallback 的第二个函数 on_mouse 是一个普通函数 (非类的成员函数)。原因是,普通函数有自己的内存地址,但是类的成员函数只有偏移量,需要和类的首地址结合才能决定。 所以,如果想把类的成员函数 (假设为 MouseFunction ) 传给 cvSetMouseCallback,需要把 MouseFunction 设置为静态 (static) 的。但是,静态的成员函数不能访问非静态的类成员变量。 进一步考虑,类静态函数之所以不能访问非静态的类成员变量,原因是不能传入类的 this 指针,因为静态函数没有绑定到具体的实例。 于是,可以人工传入类的 this 指针。 再看 cvSetMouseCallback 的第三个参数,可以接受任意的参数void*。 在类的普通成员函数 (非静态) 中可以把类的 this 指针传给 cvSetMouseCallback 函数,如下(类的某一普通成员函数中):
cvSetMouseCallback(“ImageFirst”, &CMatch::MouseCallback, this);
其中,MouseCallback 是类 CMatch 中的一个静态 (static) 成员函数,用于定义鼠标的回调函数。自定义回调函数声明 (Declaration) 如下:
static void MouseCallback(int event, int x, int y, int flags, void* param);
static void SaveMatchPoints(CvPoint* MatchPoints, void* param);
由于很多情况下要访问类的非静态成员变量,而自定义回调函数 MouseCallback 确实静态 (static) 的,不能直接访问非静态的类成员变量,此时可以通过传入类的 this 指针来进行非静态的类成员变量的访问。
函数定义 (Definition) 如下:
void CMatch::MouseCallback(int event, int x, int y, int flags, void* param);
{
CvPoint* MatchPoints;
CMatch* match = (CMatch*)param;
……
// SaveMatchPoints 用于对类 CMatch 中某非静态成员变量进行访问处理
SaveMatchPoints(MatchPoints, match);
}
void CMatch::SaveMatchPoints(CvPoint* MatchPoints, void* param)
{
CMatch* match = (CMatch*)param;
……
}
本文链接:http://www.yongblog.com/archives/194.html 转载请注明出处。