OpenCV中的鼠标操作和滑动条的消息映射方式比较类似,都是通过一个中介函数配合一个回调函数来实现的。创建和指定滑动条回调函数的函数为createTrackbar,而指定鼠标操作消息回调函数的函数为SetMounseCallback。
下面我们一起来看一下它
SetMouseCallback函数的作用是为指定的窗口设置鼠标回调函数,原型如下:
C++:void setMouseCallback( conststring&winname,MouseCallback onMouse,void* userdata=0 )
第一个参数:const string&类型的winname,窗口的名字。
第二个参数:MouseCallback类型的onMouse,指定窗口里每次鼠标事件发生的时候,被调用的函数指针。这个函数的原型的大概形式为void Foo(int event, int x, int y,int flags, void* param)。其中event是EVENT_+变量之一,x和y是鼠标指针在图像坐标系中的坐标值,flags是EVENT_FLAG的组合,param是用户定义的传递到SetMouseCallback函数调用的参数。如EVENT_MOUSEMOVE为鼠标移动消息、EVENT_LBUTTONDOWN为鼠标左键按下消息等。(在OpenCV2中,上述“EVENT_”之前可以加上“CV_”前缀)。
第三个参数:void*类型的userdata,用户定义的传递到回调函数的参数,有默认值0。
下面看一下详细注释的示例程序,在实战中了解此函数的用法以及如何在OpenCV中使用鼠标进行交互。
#include
using namespace cv;
Using namespace std;
#define WINDOW_NAME "【鼠标相关操作】"
void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRactangle(Mat& img, Rect box);
Rect g_rectangle;
bool g_bDrawingBox = false;//是否进行绘制
RNG g_rng(12345);
int main(int argc, char** argv)
{
//准备参数
g_rectangle = Rect(-1, -1, 0, 0);
Mat srcImage(600, 800, CV_8UC3), tempImage;
srcImage.copyTo(tempImage);
g_rectangle = Rect(-1, -1, 0, 0);
srcImage = Scalar::all(0);
// 设置鼠标操作回调函数
namedWindow(WINDOW_NAME);
setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);
// 程序主循环,当进行绘制的标识符为真的时候进行绘制
while (1)
{
srcImage.copyTo(tempImage); // 复制源图到临时变量
if (g_bDrawingBox)
{
DrawRactangle(tempImage, g_rectangle); //进行绘制
}
imshow(WINDOW_NAME, tempImage);
if (waitKey(10) == 27) // 按下ESC键,程序退出
break;
}
return 0;
}
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
Mat& image = *(Mat*)param;
switch (event)
{
case EVENT_MOUSEMOVE:
{
if (g_bDrawingBox) //如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
{
g_rectangle.width = x - g_rectangle.x;
g_rectangle.height = y - g_rectangle.y;
}
}
break;
// 左键按下消息
case EVENT_LBUTTONDOWN:
{
g_bDrawingBox = true;
g_rectangle = Rect(x, y, 0, 0); //记录起点
}
break;
//左键抬起消息
case EVENT_LBUTTONUP:
{
// 标识符为false
g_bDrawingBox = false;
//对宽和高小于0的处理
if (g_rectangle.width < 0)
{
g_rectangle.x += g_rectangle.width;
g_rectangle.width *= -1;
}
if (g_rectangle.height < 0)
{
g_rectangle.y += g_rectangle.height;
g_rectangle.height *= -1;
}
//调用函数进行绘制
DrawRactangle(image, g_rectangle);
}
break;
}
}
void DrawRactangle(Mat& img, Rect box)
{
// tl(top left) br(below right)
rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));
}
首先一起看一下程序的运行效果。我们可以通过鼠标左键的按下和松开来在黑色的窗口中绘制出一个一个彩色的矩形。
上面例子中的on_MouseHandle就是我们的鼠标消息回调函数。其中用一个switch语句指出了各种类型的鼠标消息,如鼠标移动消息EVENT_MOUSEMOVE、左键按下消息EVENT_LBUTTONDOWN、左键抬起消息EVENT_LBUTTONUP,并对其进行处理,以得到随机颜色的矩形绘制的功能。