opencv 鼠标事件 setMouseCallback 心得

最近两天学习了一下opencv中的鼠标事件函数,感觉网上的体会不是特别详尽,把自己调用这个函数的体会写一下,方便以后看的时候整理思路。

一、介绍

在opencv中,对鼠标事件 setMouseCallback 的定义是

c++: CV_EXPORTS void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata = 0);
winname:窗口的名字
onMouse:鼠标响应函数,回调函数
userdate:传给回调函数的参数 ,例如当鼠标在 winname的窗口进行操作时,将指针的地址传给on mouse

而对于MouseCallback onMouse函数的定义为

typedef void (MouseCallback)(int event, int x, int y, int flags, void userdata);
即onMouse函数的原型应该为 void on_Mouse(int event, int x, int y, int flags, void* userdata);
event为 CV_EVENT_*所定义,代表鼠标点击事件,每当鼠标有点击事件发生,就把相应数字传给on_Mouse函数,以进行下一步处理。
x为鼠标当前所在位置的x坐标。
y为鼠标当前所在位置的y坐标
flags为CV_EVENT_FLAG所定义,代表鼠标拖拽事件

C++中,event的对应事件为

enum
{
CV_EVENT_MOUSEMOVE =0,//滑动
CV_EVENT_LBUTTONDOWN =1,//左键点击
CV_EVENT_RBUTTONDOWN =2,//右键点击
CV_EVENT_MBUTTONDOWN =3,//中键点击
CV_EVENT_LBUTTONUP =4,//左键放开
CV_EVENT_RBUTTONUP =5,//右键放开
CV_EVENT_MBUTTONUP =6,//中键放开
CV_EVENT_LBUTTONDBLCLK =7,//左键双击
CV_EVENT_RBUTTONDBLCLK =8,//右键双击
CV_EVENT_MBUTTONDBLCLK =9//中键双击
};

C++中,flags的对应事件为

enum
{
CV_EVENT_FLAG_LBUTTON =1,//左键拖拽
CV_EVENT_FLAG_RBUTTON =2,//右键拖拽
CV_EVENT_FLAG_MBUTTON =4,//中键拖拽
CV_EVENT_FLAG_CTRLKEY =8,//按CTRL不放
CV_EVENT_FLAG_SHIFTKEY =16,//按SHIFT不放
CV_EVENT_FLAG_ALTKEY =32//按ALT不放
};

二、取点

利用setMouseCallback 对获取的图像取点并显示

#include<opencv2\opencv.hpp>
#include<iostream>

using namespace cv;
using namespace std;

Mat srcImg,tmpImg, MidImg;

void on_mouse(int EVENT, int x, int y, int flags, void* ustc);

int main(void)
{
	srcImg = imread("1.jpg");
	namedWindow("DealImg", WINDOW_NORMAL);
	srcImg.copyTo(tmpImg);
	imshow("DealImg", tmpImg);
	setMouseCallback("DealImg", on_mouse, (void*)(&tmpImg)); //调用回调函数 
 	waitKey(0);
	destroyWindow("DealImg");
		
	rectangle(srcImg, Handle_rect, Scalar(255, 0, 0), 3, 8, 0);//能够实时显示在画矩形窗口时的痕迹
}
void on_mouse(int EVENT, int x, int y, int flags, void* ustc)
{
	Pre_pt = Point(x, y);
	sprintf(Txt_Point, "(%d,%d)", x, y);
	putText(tmpImg, Txt_Point, Pre_pt,	
         CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);
	circle(tmpImg, Pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);//划圆 			
	imshow("DealImg", tmpImg);
}

处理的效果如下
在这里插入图片描述

三、画框

利用setMouseCallback 对获取的图像画框并显示

#include<opencv2\opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std;

Mat srcImg,tmpImg, MidImg;

int main(void)
{
	srcImg = imread("2.jpg");
	namedWindow("DealImg", WINDOW_NORMAL);
	srcImg.copyTo(tmpImg);	
	imshow("DealImg", tmpImg);
	setMouseCallback("DealImg", on_mouse, (void*)(&tmpImg)); //调用回调函数 
 	waitKey(0);
	destroyWindow("DealImg");
}

void on_mouse(int EVENT, int x, int y, int flags, void* ustc)
{
	static Point Pre_pt(-1, -1);
	static Point Cur_pt(-1, -1);
	char Txt_Point[50] = { 0 };

	if (ustc == NULL)
	{
		return;
	}

	if (EVENT == CV_EVENT_LBUTTONDOWN)                                      //左键按下,读取初始坐标,并在图像上该点处划圆 
	{
		Pre_pt = Point(x, y);
		sprintf(Txt_Point, "(%d,%d)", x, y);
		putText(tmpImg, Txt_Point, Pre_pt,CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);
		circle(tmpImg, Pre_pt, 2, Scalar(255, 0, 0, 0), CV_FILLED, CV_AA, 0);    //左键按下的点划圆 			
		imshow("DealImg", tmpImg);
	}

	else if ((EVENT == CV_EVENT_MOUSEMOVE) && !(flags & CV_EVENT_FLAG_LBUTTON))//左键没有按下的情况下鼠标移动的处理函数
	{
		if (MidImg.data == NULL)
		{
			srcImg.copyTo(tmpImg);                                            //将src复制到临时图像tmp上,用于显示实时坐标  
		}
		else
		{
			MidImg.copyTo(tmpImg);                                             //当已划定矩形的情况时,在图像上显示前面所画图像
		}
		Cur_pt = Point(x, y);
		sprintf(Txt_Point, "(%d,%d)", x, y);
		putText(tmpImg, Txt_Point, Cur_pt,CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);
		imshow("DealImg", tmpImg);
	}

	else if (EVENT == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))//左键按下时,鼠标移动,则在图像上划矩形 
	{
		srcImg.copyTo(MidImg);
		Cur_pt = Point(x, y);
		sprintf(Txt_Point, "(%d,%d)", x, y);
		putText(MidImg, Txt_Point, Pre_pt,CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);
		rectangle(MidImg, Cur_pt, Pre_pt, Scalar(0, 0, 255), 1, 8, 0);
		imshow("DealImg", MidImg);
	}
	else if (EVENT == CV_EVENT_LBUTTONUP)                                          //左键松开,将在图像上划矩形 
	{
		srcImg.copyTo(MidImg);
		sprintf_s(Txt_Point, "(%d,%d)", x, y);
		Cur_pt = Point(x, y);
		putText(MidImg, Txt_Point, Pre_pt,CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);
		putText(MidImg, Txt_Point, Cur_pt,CV_FONT_HERSHEY_COMPLEX, 0.5, Scalar(0, 0, 0, 255), 1, 8);
		rectangle(MidImg, Cur_pt, Pre_pt, Scalar(0, 0, 255), 1, 8, 0);
		imshow("DealImg", MidImg);
	}
}

处理的效果如下
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_38134868/article/details/82782547
今日推荐