鼠标的使用
鼠标函数的定义
void cv::setMouseCallback (
const String & winname,
MouseCallback onMouse,
void * userdata = 0 )
这个函数定义包含了三个参数,分别是把鼠标函数放置在哪个窗口,鼠标事件发生的时候调用哪个回调函数,以及向回调函数中传递什么数值。
回调函数的定义
回调函数必须满足下面的结构
void MouseCallback(
int event,
int x,
int y,
int flag,
void *userdata
)
第一个参数event,是一个int类型的变量,用来接收具体接收到了哪一种类型的鼠标事件,这里简略举几个例子
变量名 | 意义 |
---|---|
EVENT_MOUSEMOVE | 鼠标移动 |
EVENT_LBUTTONDOWN | 鼠标左键按下 |
EVENT_RBUTTONDOWN | 鼠标右键按下 |
EVENT_LBUTTONUP | 鼠标左键松开 |
EVENT_RBUTTONUP | 鼠标右键松开 |
第二个和第三个参数用来接收鼠标的坐标位置,这个位置是图片的作伴,不是窗口的坐标
第四个参数flag,意义与event参数比较相似,具有指示鼠标按下事件完成、shift键按下等检查功能。
具体例子
这个例子是参考《Opencv3编程入门》写下来的(p79页)
下面这个程序的运行思路为,当鼠标左键按下的时候开始绘图,鼠标左键松开的时候结束绘图,鼠标移动的偏移量作为图片的长和宽。srcImage图片作为底片,上面绘制的矩形边长是鼠标按下到松开的偏移量。而tempImage图片是一个中间量,绘制的是从鼠标左键按下到鼠标左键松开这个过程的所有矩形。不过按书中的程序,对srcImage图片绘制边长为负值的时候做了校正,但是这个步骤却没有对tempImage做。
但是我发现并不需要对rect矩形的坐标进行重新变换,width和height都是负值的时候,仍然可以正常的绘图。
#include<opencv2/opencv.hpp>
using namespace cv;
//程序说明:实现功能为鼠标按下后可以拖动进行绘制矩形框
bool g_value = false;//全局变量,用来判断什么时候开始画矩形框
Rect g_rect(-1,-1,0,0);//用来绘图的矩阵
void DrawRectangle(Mat& m, Rect r) //用来绘制矩形的函数
{
Scalar s(255, 0, 255);//相当于定义三通道的颜色,三通道分别是255,0,255
rectangle(m, g_rect, s);//用定义的颜色s,在图像m中绘制矩形g_rect
}
void MouseCallBack(int event,int x,int y,int flags,void* param)//回调函数
{
Mat m = *(Mat*)param;
switch (event)
{
case(EVENT_MOUSEMOVE):
if (g_value)//如果鼠标左键按下,g_value变为真,运行进行绘图,绘图矩阵记录鼠标移动的距离,作为宽和高
{
g_rect.width = x - g_rect.x;
g_rect.height = y - g_rect.y;
}
break;
case(EVENT_LBUTTONDOWN): //鼠标左键按下的时候,给矩阵重新定义初始位置
g_value = true;
g_rect = Rect(x, y, 0, 0);
break;
case(EVENT_LBUTTONUP): //鼠标左键放开的时候,把矩形画入srcImage。
g_value = false;
DrawRectangle(m, g_rect);
break;
}
}
int main()
{
Mat srcImage, tempImage; //两个用来存放图片的变量,在绘图中srcImage绘制最后的图片,tempImage绘制绘制中间过程的图片
srcImage = imread("1.jpg");
srcImage.copyTo(tempImage);
namedWindow("a", WINDOW_AUTOSIZE);
setMouseCallback("a", MouseCallBack, (void*)&srcImage); //鼠标函数
while(1)
{
srcImage.copyTo(tempImage);
if (g_value)
{
DrawRectangle(tempImage, g_rect); //这句话实际上是在记录整个鼠标的移动过程
}
imshow("a", tempImage);
if (waitKey(10) == 27)break;//按ESC键退出
}
return 0;
}
运行效果如下: