OPENCV回调函数

来源:互联网 发布:齐天大圣 知乎 编辑:程序博客网 时间:2024/05/16 14:46
OPENCV回调函数
     

回调函数

        回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

    中文名   回调函数                         意思     通过函数指针调用的函数
    外文名   Callback Functions          作用     对事件或条件进行响应

机制
⑴定义一个回调函数;
⑵函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者;
⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理。


什么是回调函数?
  回调函数是应用程序提供给Windows系统DLL或其它DLL调用的函数,一般用于截获消息、获取系统信息或处理异步事件。应用程序把回调函数的地址指针告诉DLL,而DLL在适当的时候会调用该函数。回调函数必须遵守事先规定好的参数格式和传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自己定义调用方式,但客户程序也必须遵守相同的规定。在__stdcall方式下,函数的参数按从右到左的顺序压入堆栈,除了明确指明是指针或引用外,参数都按值传递,函数返回之前自己负责把参数从堆栈中弹出。

在什么情况下使用?

        用过STL的人都知道,在STL中众多算法和程序都用到回调函数,这实现了一种策略。只要任何符合我的标准的函数和计算都可以用我这个公式。你可以实现各种各样的回调函数,只要符合我的格式就能用。

就上面的程序来说,你只要函数格式符合cllback第二个参数的格式不论你给别人做饭、铺床叠被都可以正常工作。这就是回调的作用,把回调实现留给别人。

这是一个用法。

 

        有一位朋友用分层的概念来解释了回调机制:callback函数为B层,main函数和print*函数为A层,A层调用了B层的回调函数callmeback,而B层的回调函数调用了A层的实现函数print*。说白了B层就是一个接口。





<span style="font-size:12px;">/* License:Oct. 3, 2008Right to use this code in any way you want without warrenty, support or any guarentee of it working.BOOK: It would be nice if you cited it:Learning OpenCV: Computer Vision with the OpenCV Libraryby Gary Bradski and Adrian KaehlerPublished by O'Reilly Media, October 3, 2008*/#include <cv.h>#include <highgui.h>// 定义初始化鼠标事件的回调函数.void my_mouse_callback(int event, int x, int y, int flags, void* param);CvRect box;bool drawing_box = false;// 在一个图像上画一个框的子程序void draw_box(IplImage* img, CvRect rect)     {  //  cvRectangle  函数功能: 通过对角线上的两个顶点绘制简单、指定粗细或者带填充的矩形       cvRectangle(img,cvPoint(box.x, box.y),cvPoint(box.x + box.width, box.y + box.height),cvScalar(0xff, 0x00, 0x00)    /* red */);    }int main(int argc, char* argv[]) {    box = cvRect(-1, -1, 0, 0);    IplImage* image = cvCreateImage(cvSize(700, 700),IPL_DEPTH_8U,3);    cvZero(image);    IplImage* temp = cvCloneImage(image);    cvNamedWindow("Box Example");    // 在OPENCV中通过 cvSetMouseCallback 函数注册回调函数 ,指定鼠标事件的回调函数。    // 鼠标回调函数的参数,必须满足一定的格式要求: void cvmousecallback( int event, int x, int y, int flags, void* param);    // 第一个参数为鼠标事件类型,第二个第三个参数为事件发生时鼠标位置坐标,值得指出的是这些坐标是相对于像素位置的坐标,与窗口大小无关。    cvSetMouseCallback("Box Example",my_mouse_callback,(void*)image);    while (1)     {        cvCopyImage(image, temp);// cvcopy : 拷贝一个数组给另一个数组         if (drawing_box) draw_box(temp, box);        cvShowImage("Box Example", temp);        if (cvWaitKey(15) == 27) break;    }    // 退出程序时,释放资源    cvReleaseImage(&image);    cvReleaseImage(&temp);    cvDestroyWindow("Box Example");}// 这是我们鼠标的回调函数定义。如果用户按下鼠标左按钮,则开始画一个方框,当用户释放该按钮时,//然后我们添加方框到当前图像。当鼠标被拖动时(同时按钮按下)调整框大小。void my_mouse_callback(int event, int x, int y, int flags, void* param)    {// 鼠标回调函数的参数,必须满足一定的格式要求: void cvmousecallback( int event, int x, int y, int flags, void* param);// 第一个参数为鼠标事件类型,第二个第三个参数为事件发生时鼠标位置坐标,值得指出的是这些坐标是相对于像素位置的坐标,与窗口大小无关。      IplImage* image = (IplImage*)param;      switch (event)         {            case CV_EVENT_MOUSEMOVE:                 {                     if (drawing_box)                     {                     box.width = x - box.x;                     box.height = y - box.y;                   }                 }            break;            case CV_EVENT_LBUTTONDOWN:                 {                  drawing_box = true;                  box = cvRect(x, y, 0, 0);                }            break;            case CV_EVENT_LBUTTONUP:                 {                  drawing_box = false;                  if (box.width<0)                         {                             box.x += box.width;                             box.width *= -1;                         }                 if (box.height<0)                         {                             box.y += box.height;                             box.height *= -1;                        }                 draw_box(image, box);                }            break;    }}</span>




1 0
原创粉丝点击