学习OpenCV(第四章 鼠标事件)

工作中常常需要用户与窗口之间进行交互,最常见的就是鼠标和键盘事件,鼠标事件的响应采用回调函数的方式来处理。首先必须创建一个回调函数,然后在OpenCV中注册这个函数,当特定鼠标点击事件发生时OpenCV可以调用这个被注册的函数处理事件。

回调函数:

CvMouseCallback(
    int event,   //鼠标事件类型
    int x,       //事件发生时鼠标坐标值
    int y,
    int flags,   //指定在事件发生时的不同状态,如Shift键是否按下
    void *param  //传递额外的参数信息
)

注册函数:

void cvSetMouseCallback(
    const char* window_name,  //指定回调函数注册到的窗口
    CvMouseCallback on_mouse, //回调函数
    void* param = NULL  // 传递额外的参数信息
)

刚看完《学习OpenCV》114页,敲了一遍例4-1,遇到一个问题。如果my_mouse_callback声明和函数体分离(见程序1),运行报错,但如果把my_mouse_callback函数声明与函数体写在一起却可以运行(见程序2)。还没有找到原因!

程序1:

#include <cv.h>
#include <highgui.h>

CvRect box;
bool drawing_box = false;

void draw_box(IplImage *img, CvRect rect)
{
    cvRectangle(
        img,
        cvPoint(box.x, box.y),
        cvPoint(box.x + box.width, box.y + box.height),
        cvScalar(0xff, 0x00, 0x00)
        );
}

void my_mouse_callback(int event, int x, int y, int flag, void* param);

int main()
{
    box = cvRect(-1, -1, 0, 0);

    IplImage *image = cvLoadImage("2-1.jpg");
    IplImage *temp = cvCloneImage(image);
    cvNamedWindow("Box Example");

    cvSetMouseCallback("Box Example", my_mouse_callback, (void*)image);

    while (1)
    {
        cvCopy(image, temp);
        if (drawing_box) draw_box(temp, box);
        cvShowImage("Box Example", temp);
        if (cvWaitKey(15) == 27)break;
    }

    cvReleaseImage(&image);
    cvReleaseImage(&temp);
    cvDestroyWindow("Box Example");

    return 0;
}

void my_mouse_callback(int event, int x, int y, 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;

    default:
        break;
    }
}

这里写图片描述

程序2:

#include <cv.h>
#include <highgui.h>


CvRect box;
bool drawing_box = false;

void draw_box(IplImage *img, CvRect rect)
{
    cvRectangle(
        img,
        cvPoint(box.x, box.y),
        cvPoint(box.x + box.width, box.y + box.height),
        cvScalar(0xff, 0x00, 0x00)
        );
}

void my_mouse_callback(int event, int x, int y, int flag, 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;

    default:
        break;
    }
}

int main()
{
    box = cvRect(-1, -1, 0, 0);

    IplImage *image = cvLoadImage("2-1.jpg");
    IplImage *temp = cvCloneImage(image);
    cvNamedWindow("Box Example");

    cvSetMouseCallback("Box Example", my_mouse_callback,(void*)image);

    while (1)
    {
        cvCopy(image, temp);
        if (drawing_box) draw_box(temp, box);
        cvShowImage("Box Example", temp);
        if (cvWaitKey(15) == 27)break;
    }

    cvReleaseImage(&image);
    cvReleaseImage(&temp);
    cvDestroyWindow("Box Example");

    return 0;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值