1. 程式人生 > >opencv 滑鼠事件 setMouseCallback 心得

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;

unsigned char DrawFrame_OR_GetPoint = 1;        //1畫框,2取點
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);
	}
}

處理的效果如下 在這裡插入圖片描述