C++ OpenCV #007 鼠标操作
opencv的setMouseCallback()函数能够监听鼠标的操作与响应,此函数会在调用之后不断查询鼠标信息直到窗口销毁
1. 鼠标监听与响应
-
注意操作范围是在图像范围,在创建或读取的图像中点击鼠标才能监听
-
监听事件:按下鼠标,鼠标移动,鼠标弹起
-
响应:当监听到相应的事件时,我们可以编写对应的响应
2. 测试
-
函数原型:
setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);winname:窗口名称
onMouse:回调函数名称
userdata:用户数据
-
回调函数:
on_mouse(int event, int x, int y, int flags, void* userdata)event:监听的事件
x:当前x坐标
y:当前y坐标
flags:代表鼠标的拖拽事件
userdata:用户数据
-
常用的监听事件:
// Event: 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 //中键双击 // FLAG: EVENT_FLAG_LBUTTON 1 //左鍵拖曳 EVENT_FLAG_RBUTTON 2 //右鍵拖曳 EVENT_FLAG_MBUTTON 4 //中鍵拖曳 EVENT_FLAG_CTRLKEY 8 //(8~15)按Ctrl不放事件 EVENT_FLAG_SHIFTKEY 16 //(16~31)按Shift不放事件 EVENT_FLAG_ALTKEY 32 //(32~39)按Alt不放事件 -
程序:注意,旧版本事件需要加
CV_,新版本取消#include <opencv2/opencv.hpp> #include <opencv2/core/utils/logger.hpp> #include<iostream> using namespace std; using namespace cv; int num; //记录调用次数 void close_log() { utils::logging::setLogLevel(utils::logging::LOG_LEVEL_ERROR); } //鼠标回调函数 void on_mouse(int event, int x, int y, int flags, void* userdata) { num++; cout << "第 " << num << " 次回调鼠标事件" << endl; if (event == EVENT_MOUSEMOVE) { cout << "触发鼠标移动事件" << endl; } if (event == EVENT_LBUTTONDOWN) { cout << "触发左键按下事件" << endl; } if (event == EVENT_LBUTTONUP) { cout << "触发左键抬起事件" << endl; } if (event == EVENT_RBUTTONDOWN) { cout << "触发右键按下事件" << endl; } if (event == EVENT_RBUTTONUP) { cout << "触发右键抬起事件" << endl; } if (event == EVENT_LBUTTONDBLCLK) { cout << "触发左键双击事件" << endl; } if (event == EVENT_RBUTTONDBLCLK) { cout << "触发右键双击事件" << endl; } } int main() { // 关闭日志 close_log(); // 创建画布 Mat image(512, 512, CV_8UC3, Scalar(0, 0, 0)); imshow("image", image); // 鼠标事件监听 setMouseCallback("image", on_mouse, 0); waitKey(); system("pause"); } -
运行结果:注意要在图像范围内操作鼠标才会被监听

3. 案例:
使用鼠标进行动态矩形绘制
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/logger.hpp>
#include<string>
#include<iostream>
using namespace std;
using namespace cv;
// 定义全局变量
Mat canvas(512, 512, CV_8UC3, Scalar(0, 0, 0));
Mat temp = canvas.clone(); // 把原图复制一份
Point pt;
bool flag;
void close_log() {
utils::logging::setLogLevel(utils::logging::LOG_LEVEL_ERROR);
}
void on_mouse(int event, int x, int y, int flags, void* userdata) {
// 先把 void* 转为 Mat* 再解引用,即img和canvas指向同一个数据
// Mat canvas = *(Mat*)userdata;
switch (event) {
case EVENT_LBUTTONDOWN:
// 添加点pt,接收鼠标左键按下时的(x,y)
pt.x = x;
pt.y = y;
// 鼠标左键按下后,flag置为真
flag = true;
break;
case EVENT_MOUSEMOVE:
if (flag) {
// 把 temp 拷贝给 canvas,temp为源图片(无任何内容)
// 每移动鼠标,先把画布用原图覆盖,再绘制矩形
temp.copyTo(canvas);
// 画矩形的两点,point1 按下鼠标的点,point2 鼠标移动的点
rectangle(canvas, Point(pt.x, pt.y), Point(x, y), Scalar(0, 0, 255), 1, 8, 0);
}
break;
case EVENT_LBUTTONUP:
// 鼠标左键按弹起,flag置为假。
flag = false;
break;
default:
break;
}
}
void image_process() {
namedWindow("draw", WINDOW_AUTOSIZE);
setMouseCallback("draw", on_mouse, 0);
// 不断调用回调函数,如果waitKey(0)则会堵塞窗口
while (1) {
imshow("draw", canvas);
if (waitKey(10) == 27) {
break;
}
}
}
int main() {
close_log();
image_process();
return 0;
}
运行结果:

本文来自博客园,作者:{枫_Null},转载请注明原文链接:https://www.cnblogs.com/fengNull/articles/16686237.html

浙公网安备 33010602011771号