首页 > 编程笔记 > C++笔记 阅读:10

OpenCV鼠标事件详解(附带实例)

在 OpenCV 中存在鼠标的操作,比如单击、双击等。对于 OpenCV 来讲,用户的鼠标操作被认为发生了一个鼠标事件,需要对这个鼠标事件进行处理,这就是事件的响应。

鼠标事件包括左键按下、左键松开、左键双击、鼠标移动等。当鼠标事件发生时,OpenCV 会让一个鼠标响应函数自动被调用,相当于一个回调函数,这个回调函数就是鼠标事件处理函数。

OpenCV 提供了 setMousecallback() 来预先设置回调函数,相当于告诉系统鼠标处理的回调函数已经设置好了,有鼠标事件发生时,系统调用这个回调函数即可。注意是系统调用,而不是开发者调用,因此称为回调函数。

函数 setMousecallback() 声明如下:
void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0);
其中参数 winname 表示窗口的名字,onMouse 是鼠标事件响应的回调函数指针,userdate 是传给回调函数的参数。这个函数名也比较形象,一看就知道是用来设置鼠标回调函数的(set Mouse call back)。

鼠标事件回调函数类型 MouseCallback 定义如下:
typedef void(* cv::MouseCallback)(int event, int x, int y, int flags, void *useradata);
其中参数 event 表示鼠标事件,x 表示鼠标事件的 x 坐标,y 表示鼠标事件的 y 坐标,flags 表示鼠标事件的标志,userdata 是可选的参数。

鼠标事件 event 主要有以下几种:
enum
{
    EVENT_MOUSEMOVE      =0,   // 滑动
    EVENT_LBUTTONDOWN    =1,   // 左键单击
    EVENT_RBUTTONDOWN    =2,   // 右键单击
    EVENT_MBUTTONDOWN    =3,   // 中键单击
    EVENT_LBUTTONUP      =4,   // 左键放开
    EVENT_RBUTTONUP      =5,   // 右键放开
    EVENT_MBUTTONUP      =6,   // 中键放开
    EVENT_LBUTTONDBLCLK   =7,  // 左键双击
    EVENT_RBUTTONDBLCLK   =8,  // 右键双击
    EVENT_MBUTTONDBLCLK   =9   // 中键双击
};

鼠标事件标志 flags 主要有以下几种:
enum {
    EVENT_FLAG_LBUTTON = 1,    // 左键拖曳
    EVENT_FLAG_RBUTTON = 2,    // 右键拖曳
    EVENT_FLAG_MBUTTON = 4,    // 中键拖曳
    EVENT_FLAG_CTRLKEY = 8,    // 按Ctrl
    EVENT_FLAG_SHIFTKEY = 16,  // 按Shift
    EVENT_FLAG_ALTKEY = 32     // 按Alt
};
通过 event 和 flags 就能清楚地了解当前鼠标发生了哪种操作。

【实例】在图片上用鼠标画线。
1) 打开 Qt Creator,新建一个控制台工程,工程名是 test。

2) 在 IDE 中打开 main.cpp,输入如下代码:
#include <opencv2/opencv.hpp>
using namespace cv;
#include<iostream>
using namespace std;
#define WINDOW "原图"
Mat g_srcImage, g_dstImage;
Point previousPoint;
bool P = false;
void on_mouse(int event, int x, int y, int flags, void*);

int main()
{
    g_srcImage = imread("ter.jpg", 1);
    imshow(WINDOW, g_srcImage);
    setMouseCallback(WINDOW, On_mouse, 0);
    waitKey(0);
    return 0;
}

void on_mouse(int event, int x, int y, int flags, void*)
{
    if (event == EVENT_LBUTTONDOWN)
    {
        previousPoint = Point(x, y);
    }
    else if (event == EVENT_MOUSEMOVE && (flags&EVENT_FLAG_LBUTTON))
    {
        Point pt(x, y);
        line(g_srcImage, previousPoint, pt, Scalar(0, 255), 2, 5, 0);
        previousPoint = pt;
        imshow(WINDOW, g_srcImage);
    }
}
在上述代码中,on_mouse 就是用来处理鼠标事件的回调函数,当鼠标有动作产生时,on_mouse 会被系统调用,然后在 on_mouse 中判断发生了哪种动作,进而进行相应的处理。

本例我们关心的是按下鼠标左键,然后按住左键时的鼠标移动。一旦按下鼠标左键,就记录下当时的位置(也就是画线的开始点),位置记录在 previousPoint 中。接着如果继续有鼠标移动事件发生,我们就开始调用函数 line 画线。最后把画了线的图像数据 g_srcImage 用函数 imshow 显示出来。

3) 保存工程并运行,结果如下图所示:

相关文章