【OpenCV】OpenCV實戰從入門到精通之七 -- 教你如何使用鼠標操作SetMouseCallback

本文是《OpenCV實戰從入門到精通》系列之第7篇

【OpenCV】OpenCV實戰從入門到精通之一 -- OpenCV宏的講解

【OpenCV】OpenCV實戰從入門到精通之二 -- OpenCV如何進行圖像腐蝕操作

【OpenCV】OpenCV實戰從入門到精通之三 -- canny邊緣檢測

【OpenCV】OpenCV實戰從入門到精通之四 -- 常用的函數講解(mat、imread、imshow、imwrite、nameWindow)

【OpenCV】OpenCV實戰從入門到精通之五 -- 教你使用Rect()函數

【OpenCV】OpenCV實戰從入門到精通之六 -- 教你如何使用滑動條-createTrackbar()函數

目錄

本文是《OpenCV實戰從入門到精通》系列之第7篇

函數原型

第二個參數可能不很理解,其實第二個參數最關鍵:它是我們對鼠標操作的反應,當鼠標有哪些操作,我們可以出現不同的響應。 如果我們沒有設定這些操作,那麼就不會有反應

結果 


函數原型

void setMouseCallback(conststring& winname, MouseCallback onMouse,void* userdata=0)

第一個參數:窗口名

第二個參數:被調用的函數指針。

                     函數原型:void Foo(int event,int x,int y,int flags, void *param)

第三個參數:用戶 定義的傳遞到回調函數的參數,默認0

第二個參數可能不很理解,其實第二個參數最關鍵:它是我們對鼠標操作的反應,當鼠標有哪些操作,我們可以出現不同的響應。 如果我們沒有設定這些操作,那麼就不會有反應

舉例:設定了單擊左鍵就跳出窗口,設定單擊右鍵無任何操作。那麼程序就會根據你的指令進行選擇。

//----------------【】-----------------------
//
//-------------------------------------------

//----------------【頭文件、命名空間包含範圍】-----------------------
//                   包含的命名空間和頭文件
//---------------------------------------------------------------

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

#define WINDOW_NAME "【程序窗口】"      //爲窗口標題定義宏


//----------------【全局函數聲明】-----------------------
//    提示幫助ShowHlepText
//-------------------------------------------
void on_MouseHandle(int event, int x, int y ,int flags, void* param);
void DrawRectangle(cv::Mat& img, cv::Rect box);
void ShowHlepText();

//----------------【全局變量聲明的部分】-----------------------
//
//-------------------------------------------
Rect g_rectangle;//長方形
bool g_bDrawingBox = false;//是否進行繪製
RNG g_rng(12345);

//----------------【main()函數】-----------------------
//
//-------------------------------------------
int main()
{
	//【1】準備參數
	g_rectangle = Rect(-1,-1,0,0);
	Mat srcImage(600, 800, CV_8UC3), tempImage;//生成一個600x800的窗口
	srcImage.copyTo(tempImage);
	g_rectangle = Rect(-1, -1, 0, 0);
	srcImage = Scalar::all(0);

	//【2】設置鼠標回調函數
	namedWindow(WINDOW_NAME);
	setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);//爲指定窗口設定回調函數,也就是自己設定判斷鼠標操作

	//【3】程序的主循環,當繪製標識符爲真,進行繪製
	while (1)
	{
		srcImage.copyTo(tempImage); //複製到臨時變量
		if (g_bDrawingBox) //標識符爲真,就繪製
			DrawRectangle(tempImage, g_rectangle);
		imshow(WINDOW_NAME, tempImage);
		if (waitKey(10) == 27) break; //按下Esc鍵,程序退出
	}
	return 0;
}

//----------------【on_MouseHandle()函數】-----------------------
//   記錄鼠標的信息,比如鼠標移動、左鍵按鍵
//-------------------------------------------
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
	Mat& image = *(cv::Mat*) param;
	switch (event)
	{
		//鼠標移動
		case EVENT_MOUSEMOVE:
		{
								if (g_bDrawingBox)
								{
									g_rectangle.width = x - g_rectangle.x;
									g_rectangle.height = y - g_rectangle.y;
								}
		}
		    break;
		
		//左鍵按下消息
		case EVENT_LBUTTONDOWN:
		{
								  g_bDrawingBox = true;
								  g_rectangle = Rect(x, y, 0, 0);//記錄起始點
		}
			break;

		//左鍵擡起消息
		case EVENT_LBUTTONUP:
		{
								g_bDrawingBox = false;
								//對寬、高小於0如何處理
								if (g_rectangle.width < 0)
								{
									g_rectangle.x + g_rectangle.width;
									g_rectangle.width *= -1;
								}

								if (g_rectangle.height < 0)
								{	
									g_rectangle.y += g_rectangle.height;
									g_rectangle.height *= -1;
								}
								//調用函數繪製
								DrawRectangle(image, g_rectangle);
		}
			break;

	}
}

//----------------【DrawRectangle()函數】-----------------------
//
//-------------------------------------------
void DrawRectangle(cv::Mat& img, cv::Rect box)
{
	rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));//隨機顏色,(左上角+右下角頂點)
}

結果 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章