opencv中进行鼠标操作主要用到setMouseCallback这个函数,如下:
void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);
winname:窗口名称
onMouse:鼠标响应函数,回调函数
userdata:用户自定义的参数
此函数会在调用之后不断查询鼠标信息直到窗口销毁
主要操作在回调函数onMouse中设置:
void on_Mouse(int event, int x, int y, int flags, void* param);
event:表示鼠标事件类型的常量
x和y:鼠标指针在图像坐标系的坐标
flags:鼠标事件标志的常量
param:用户可自定义的参数
鼠标事件的类型(字母和数字完全等价):
Event:
#define CV_EVENT_MOUSEMOVE 0 //滑动
#define CV_EVENT_LBUTTONDOWN 1 //左键点击
#define CV_EVENT_RBUTTONDOWN 2 //右键点击
#define CV_EVENT_MBUTTONDOWN 3 //中键点击
#define CV_EVENT_LBUTTONUP 4 //左键放开
#define CV_EVENT_RBUTTONUP 5 //右键放开
#define CV_EVENT_MBUTTONUP 6 //中键放开
#define CV_EVENT_LBUTTONDBLCLK 7 //左键双击
#define CV_EVENT_RBUTTONDBLCLK 8 //右键双击
#define CV_EVENT_MBUTTONDBLCLK 9 //中键双击
#include
#include
using namespace cv;
using namespace std;
void on_Mouse(int event, int x, int y, int flags, void* param) {
if (event == CV_EVENT_MOUSEMOVE)//鼠标移动将会触发此事件,CV_EVENT_MOUSEMOVE和0等效
cout << "x:"<
效果如下:
同理,如果将事件event改为CV_EVENT_MBUTTONDOWN或3,效果将是鼠标左键在图上点击一下,显示一次点击点坐标。
左键框选感兴趣区域:
#include "pch.h"
#include
#include
using namespace cv;
using namespace std;
Mat src,tmp,img,dst;//为了方便直接在这里初始化全局变量,也可以在mian函数中初始化通过鼠标函数中
//使用那个自定义的参数将图片传入回调函数,不过涉及一个Mat和指针类型的转换较为麻烦。
void on_Mouse(int event, int x, int y, int flags, void* param) {
static Point pre_pt = Point(-1, -1);//起始点坐标,这里不加static会出错,是因为此回调函数会
//在鼠标操作中不断执行很多次,如果不加static,起始点坐标将被不断重新赋值。
static Point cur_pt = Point(-1, -1);//终点坐标
if (event == 1)
{
pre_pt = Point(x, y);//左键按下,记录起始点坐标
cout << pre_pt << endl;
}
else if (event == CV_EVENT_MOUSEMOVE && flags == 1) {
//左键不放鼠标移动过程中实时显示框选区域
src.copyTo(tmp);
cur_pt = Point(x, y);
rectangle(tmp, pre_pt, cur_pt, Scalar(255, 255, 0, 0), 1, 8, 0);
//cout << cur_pt << endl;//实时显示坐标
imshow("src", tmp);//画的时候显示框
}
else if (event == 4)
{
src.copyTo(img);
cur_pt = Point(x, y);
cout << cur_pt << endl;
rectangle(img, pre_pt, cur_pt, Scalar(255, 255, 0, 0), 1, 8, 0);
int width = abs(pre_pt.x - cur_pt.x);
int height = abs(pre_pt.y - cur_pt.y);
dst = src(Rect(min(cur_pt.x, pre_pt.x), min(cur_pt.y, pre_pt.y), width, height));
namedWindow("dst", CV_WINDOW_NORMAL);//CV_WINDOW_NORMAL可自由调整图片大小
imshow("dst", dst);//显示所框出的感兴趣区域
//imwrite("E:/img/lina.bmp", dst);
}
}
int main()
{
src = imread("C:\\Users\\45374\\Desktop\\一些经典算法的代码整理\\code\\img\\lena.jpg");
namedWindow("src");
setMouseCallback("src", on_Mouse,0);
imshow("src", src);//imshow和setMouseCallback位置关系没有要求,setMouseCallback只有当窗口销毁之后才会停止。
waitKey(0);
}
效果如下:
注意上面有个src.copyTo(tmp);的过程,因为每次画框之后的框是无法去除的,所以框选过程中每次都需新创建一个图片来显示实时框选过程,如果不将src的图像拷贝到tmp中再进行操作,就会出现如下效果: