鼠标消息回调函数 SetMouseCallback
函数原型 c++: void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)
winname:窗口的名字
onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针
这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);
userdate:传给回调函数的参数
鼠标响应函数的参数
void on_Mouse( int event, int x, int y, int flags, void* param );
event是 CV_EVENT_*变量之一
EVENT_MOUSEMOVE 滑动
EVENT_LBUTTONDOWN 左击
EVENT_RBUTTONDOWN 右击
EVENT_MBUTTONDOWN 中键点击
EVENT_LBUTTONUP 左键放开
EVENT_RBUTTONUP 右键放开
EVENT_MBUTTONUP 中键放开
EVENT_LBUTTONDBLCLK 左键双击
EVENT_RBUTTONDBLCLK 右键双击
EVENT_MBUTTONDBLCLK 中键双击
x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系)
flags是CV_EVENT_FLAG的组合
flag的状态有:
EVENT_FLAG_LBUTTON 左键拖拽
EVENT_FLAG_RBUTTON 右键拖拽
EVENT_FLAG_MBUTTON 中键拖拽
EVENT_FLAG_CTRLKEY 按住Ctrl不放
EVENT_FLAG_SHIFTKEY 按住Shift不放
EVENT_FLAG_ALTKEY 按住Alt不放
param是用户定义的传递到setMouseCallback函数调用的参数
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
Mat src, dst;
Mat tempsrc;
void Mouse(int event, int x, int y, int flags, void* param);//鼠标操作函数
void DrawRectangle(Mat& src, Rect box);//绘制矩形函数
bool draw = false;//决定是否进行绘制的布尔旗帜draw
Rect Rectangle;//定义矩形数据类型Rectangle
RNG rng(12345);
int main()
{
src = imread("D:/实验台/机器视觉/测试图片/格子衬衫.jpg");
if (src.empty())//如果src这个数据库属性为空
{
cout << "无法打开" << endl;
return -1;
}
imshow("原图", src);
Rectangle = Rect(-1, -1, 0, 0);//定义一个空矩形模板
//Rect(x,y,width,height); 其中x,y为矩形模板的坐标(-1表示坐标为空 不在任何坐标上) width和height为矩形的宽度和高度
//为了方便显示线条重新对原图像进行处理
Mat src(600, 800, CV_8UC3);
src = Scalar::all(0);//将src所有像素值置为0 即将src变为纯黑色图片
//Mat tempsrc = Mat::zeros(src.size(), src.type());直接在原图上绘制
namedWindow("程序窗口");
setMouseCallback("程序窗口", Mouse, (void*)&src);//传入src的地址,这样就不必将img设置成全局变量了
//鼠标响应函数cv:: setMousecallback(const string & winname, MouseCallback onMouse, void* userdata = 0)
//1.winname:窗口的名字
//2. onMouse : 鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针 这个函数的原型应该为void on_Mouse(int event, int x, int y, int flags, void* param);
//3.userdate:传给回调函数的形式参数
while (1)
{
tempsrc = src.clone();//防止绘制图像粘连 要将src的值克隆给tempsrc
if (draw)//如果draw=true允许绘图
{
DrawRectangle(tempsrc, Rectangle);//调用DrawRectangle函数绘制矩形
}
imshow("程序窗口", tempsrc);
if (waitKey(10) == 27)
{
break;
}
}
waitKey(0);
return 0;
}
void Mouse(int event,int x,int y,int flags,void* param)
{
//int event -- 中断事件 并不是简单的自定义的int形式的变量名 而是CV_EVENT_*变量之一,一般为setMouseCallBack传过来固定数据,常用的几个数据为
//todoevent中有10个case事例变量
//EVENT_MOUSEMOVE 滑动 EVENT_LBUTTONDOWN 左击
//EVENT_RBUTTONDOWN 右击 EVENT_MBUTTONDOWN 中键点击
//EVENT_LBUTTONUP 左键放开 EVENT_RBUTTONUP 右键放开
//EVENT_MBUTTONUP 中键放开 EVENT_LBUTTONDBLCLK 左键双击
//EVENT_RBUTTONDBLCLK 右键双击 EVENT_MBUTTONDBLCLK 中键双击
//todoevent中有x和y两个坐标变量
//为鼠标当前所在位置的x坐标 y为鼠标当前所在位子的y坐标
//todoevent中有一个标志位flag
//todoevent中的param用来接收setMouseCallback传递过来的用户数据,为void指针类型
printf("鼠标函数的x=%d y=%d Rectangle的x=%d y=%d wid=%d hei=%d \r", x, y, Rectangle.x, Rectangle.y, Rectangle.width, Rectangle.height);
Mat& src = *(Mat*)param;//将param强制转换为Mat指针,*(Mat*)=Mat,就如*(int*)=int一样 void*为万能智能指针 可以指向任何形式的参数 而param只是指针名
switch (event)
{
case EVENT_MOUSEMOVE://如果鼠标移动
{
if (draw)//如果draw为true (允许绘制的标志位打开)
{
Rectangle.width = x - Rectangle.x;//矩形的宽度为鼠标当前的x坐标减去鼠标左键点击的那一刻赋值给矩形的左上角的x坐标
Rectangle.height = y - Rectangle.y;//矩形的度高为鼠标当前的y坐标减去鼠标左键点击的那一刻赋值给矩形的左上角的y坐标
}
}
break;
case EVENT_LBUTTONDOWN://如果鼠标左键按下
{
draw = true;//允许绘制的标志位打开 鼠标可以进行矩形绘制
Rectangle = Rect(x, y, 0, 0);//将鼠标按下时的鼠标当前的x和y坐标赋值给Rect矩形左上角x和y坐标 矩形的宽高等待 case EVENT_MOUSEMOVE的计算
}
break;
case EVENT_LBUTTONUP://如果鼠标左键松开
{
draw = false;//允许绘制的标志位关闭 鼠标暂停矩形绘制
if (Rectangle.width < 0)//如果绘制出的矩形宽度小于0(以鼠标点击时给定的矩形左上角坐标为界 向左绘制矩形时 Rectangle.width为负值)
{
Rectangle.x += Rectangle.width;//矩形左上角的坐标值为矩形左上角x坐标值加上计算出的矩形宽度值(此值为负数)
Rectangle.width *= -1;//将矩形的宽度值(负数)* -1负负得正取绝对值
//abs(Rectangle.width);取绝对值方法二
}
if (Rectangle.height < 0)
{
Rectangle.y += Rectangle.height;
Rectangle.height *= -1;
//abs(Rectangle.height);
}
}
DrawRectangle(src, Rectangle);//返回的两个实参 src为src图像 Rectangle为获取的矩形框x,y,width,height信息
break;
case EVENT_RBUTTONDOWN://如果鼠标右键点击
{
src = Scalar::all(0);//将src所有像素值置为0 即将src变为纯黑色图片 去掉绘制的线条
}
break;
}
}
void DrawRectangle(Mat & src, Rect box)//在图像中绘制矩形的函数 形参有两个 Mat类型的src图像的指针 和 Rect类型的矩形变量box 分别接收鼠标操作函数的两个实参src和Rectangle
{
rectangle(src,box.tl(),box.br(),Scalar(rng.uniform(0,255), rng.uniform(0, 255), rng.uniform(0, 255)),2);
//矩形绘制函数
//1.src-模板图像 绘制彩色线条使用CV_8UC3类型 单色线条使用CV_8UC1类型
//2.box.tl() -point2i类型的坐标变量 有两个int类型的坐标参数 对应绘制矩形时选定的 矩形左上角 角点的XY坐标
//3.box.br() -point2i类型的坐标变量 有两个int类型的坐标参数 对应绘制矩形时选定的 矩形右下角 角点的XY坐标
//todo注:rect.tl();意为返回Rectangle矩形的左上角坐标 rect.br();意为返回Rectangle矩形的右下角坐标 矩形变量Rectangle内的参数不能直接进行绘制
//矩形绘制函数示例 rectangle(src, Point2i(0, 0), Point2i(500, 500), Scalar(0, 255, 0));
}


本文介绍了如何在OpenCV中使用`SetMouseCallback`函数设置鼠标回调,详细解析了回调函数的参数及鼠标事件类型,包括鼠标滑动、点击和拖拽等,并提到了按键状态标志位的检测。
6199

被折叠的 条评论
为什么被折叠?



