OpenCV版本:OpenCV4
编程语言:C/C++
OpenCV4中提供了鼠标响应相关函数setMouseCallback()。函数原型如下:
void cv::setMouseCallback(const String& winname,
MouseCallback onMouse,
void* userdata = 0)
/*
* winname:添加鼠标响应的窗口的名字
* onMouse:鼠标响应的回调函数
* userdata:传递给回调函数的可选参数
*/
该函数能够为指定的图像窗口创建鼠标响应。第二个参数是鼠标响应的回调函数,该函数在鼠标状态发生改变时被调用,是一个MouseCallback类型的函数。
MouseCallback类型的回调函数。函数原型如下:
typedef void(*cv::MouseCallback)(int event,
int x,
int y,
int flags,
void* userdata)
/*
* event:鼠标响应事件标志,参数为EVENT_*形式
* x:鼠标指针在图像坐标系中的x坐标
* y:鼠标指针在图像坐标系中的y坐标
* flags:鼠标响应标志,参数为EVENT_FLAG_*形式
* userdata:传递给回调函数的可选参数
*/
MouseCallback类型的回调函数是一个无返回值的函数,函数名可以任意设置,有5个参数,在鼠标状态发生改变的时候被调用。
MouseCallback类型回调函数鼠标响应事件标志可选参数及含义
标志参数 | 简记 | 含义 |
---|---|---|
EVENT_MOUSEMOVE | 0 | 表示鼠标指针在窗口上移动 |
EVENT_LBUTTONDOWN | 1 | 表示按下鼠标左键 |
EVENT_RBUTTONDOWN | 2 | 表示按下鼠标右键 |
EVENT_MBUTTONDOWN | 3 | 表示按下鼠标中键 |
EVENT_LBUTTONUP | 4 | 表示释放鼠标左键 |
EVENT_RBUTTONIP | 5 | 表示释放鼠标右键 |
EVENT_MBUTTONUP | 6 | 表示释放鼠标中键 |
EVENT_LBUTTONDBLCLK | 7 | 表示双击鼠标左键 |
EVENT_RBUTTONDBLCLK | 8 | 表示双击鼠标右键 |
EVENT_MBUTTONDBLCLK | 9 | 表示双击鼠标中键 |
EVENT_MOUSEWHEEL | 10 | 正值表示向前滚动,负值表示向后滚动 |
EVENT_MOUSEHWHEEL | 11 | 正值表示向左滚动,负值表示向右滚动 |
MouseCallback类型回调函数鼠标响应标志及含义
标志参数 | 简记 | 含义 |
---|---|---|
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"键 |
鼠标响应就是当鼠标位于对应的图像窗口内时,时刻检测鼠标状态,当鼠标状态发生改变时,调用回调函数,并根据回调函数中的判断逻辑选择执行相应的操作。
直接看例程会好理解一些。绘制鼠标移动轨迹的示例程序。在该程序中,如果鼠标右键被按下,就会提示“点击鼠标左键才可以绘制轨迹”,若单机左键,就会输出当前鼠标的坐标,并将该点坐标定义为某段轨迹的起始位置。之后按住左键移动鼠标,会进入到第三个逻辑判断,绘制鼠标的移动轨迹。
#include
#include
using namespace std;
using namespace cv;
Mat img, imgPoint;
Point prePoint; // 前一刻鼠标的坐标,用于绘制直线
// 鼠标响应回调函数
void mouse(int event, int x, int y, int flags, void* userdata);
int main(void)
{
img = imread("lena.png"); // 输入图片位置
if (!img.data)
{
cout << "请确认输入图像名称是否正确!" << endl;
return -1;
}
img.copyTo(imgPoint);
imshow("图像窗口1", img);
imshow("图像窗口2", imgPoint);
// 鼠标响应函数
setMouseCallback("图像窗口1", mouse, 0);
waitKey(0);
return 0;
}
// 鼠标响应回调函数
void mouse(int event, int x, int y, int flags, void* userdata)
{
if (EVENT_RBUTTONDOWN == event) // 单击右键
cout << "点击鼠标左键才可以绘制轨迹" << endl;
if (EVENT_LBUTTONDOWN == event) // 单击左键
{
prePoint = Point(x, y);
cout << "轨迹起始坐标" << prePoint << endl;
}
// 开始绘制鼠标移动的轨迹
// 鼠标指针在窗口上移动 && 按住左键拖拽
if (EVENT_MOUSEMOVE == event && (flags & EVENT_FLAG_LBUTTON))
{
// 通过改变图像像素显示鼠标移动轨迹
imgPoint.at(y, x) = Vec3b(0, 0, 255);
imgPoint.at(y, x - 1) = Vec3b(0, 0, 255);
imgPoint.at(y, x + 1) = Vec3b(0, 0, 255);
imgPoint.at(y + 1, x) = Vec3b(0, 0, 255);
imgPoint.at(y - 1, x) = Vec3b(0, 0, 255);
imshow("图像窗口2", imgPoint);
// 通过绘制直线显示鼠标移动轨迹
Point pt(x, y); // 当前鼠标坐标
line(img, prePoint, pt, Scalar(0, 0, 255), 2, 5, 0);
prePoint = pt;
imshow("图像窗口1", img);
}
}