OpenCV3 鼠標事件和滑動條事件

鼠標事件

    cv::waitKey()函數進行鍵值輔捉,下一個邏輯事件就是對鼠標事件進行“監聽”和做出響應。
    與鍵盤不同,鼠標事件使用更傳統的回調函數函數機制來完成,這就意味着,我們必須先寫好一個回調程序,
    使得OpenCV在發生任何鼠標事件時都可以調用這個回調程序,當完成回調程序以後,需要在OpenCV中註冊這個函數,
    即告訴OpenCV這是一個正確的回調程序。
    指向回調函數的指針是 cv::MouseCallback,定義回調函數的接口協議:
  

 void your_mouse_callback
    (
        int event,        //Event type
        int x,            //x-location of mouse event
        int y,            //y-location of mouse event
        int flags,        //More details on event
        void* param        //Parameters from cv::setMouseCallback()
    );

    第一個參數爲鼠標事件類型,如下所示:
    鼠標事件類型:
      

        EVENT_MOUSEMOVE      = 0, //!< indicates that the mouse pointer has moved over the window.
        EVENT_LBUTTONDOWN    = 1, //!< indicates that the left mouse button is pressed.
        EVENT_RBUTTONDOWN    = 2, //!< indicates that the right mouse button is pressed.
        EVENT_MBUTTONDOWN    = 3, //!< indicates that the middle mouse button is pressed.
        EVENT_LBUTTONUP      = 4, //!< indicates that left mouse button is released.
        EVENT_RBUTTONUP      = 5, //!< indicates that right mouse button is released.
        EVENT_MBUTTONUP      = 6, //!< indicates that middle mouse button is released.
        EVENT_LBUTTONDBLCLK  = 7, //!< indicates that left mouse button is double clicked.
        EVENT_RBUTTONDBLCLK  = 8, //!< indicates that right mouse button is double clicked.
        EVENT_MBUTTONDBLCLK  = 9, //!< indicates that middle mouse button is double clicked.
        EVENT_MOUSEWHEEL     = 10,//!< positive and negative values mean forward and backward scrolling, respectively.
        EVENT_MOUSEHWHEEL    = 11 //!< positive and negative values mean right and left scrolling, respectively.


    第二個和第三個參數將被設置爲鼠標事件的x座標和y座標,這裏的座標是圖像上的像素座標,是獨立於窗口的
    第四個參數是標誌位,是一個bit位,每一個bit位都代表在事件發生時的不同條件。具體如下所示:
      

       EVENT_FLAG_LBUTTON   = 1, //!< indicates that the left mouse button is down.
       EVENT_FLAG_RBUTTON   = 2, //!< indicates that the right mouse button is down.
       EVENT_FLAG_MBUTTON   = 4, //!< indicates that the middle mouse button is down.
       EVENT_FLAG_CTRLKEY   = 8, //!< indicates that CTRL Key is pressed.
       EVENT_FLAG_SHIFTKEY  = 16,//!< indicates that SHIFT Key is pressed.
       EVENT_FLAG_ALTKEY    = 32 //!< indicates that ALT Key is pressed.


    第五個參數是一個void*類型的指針,OpenCV可以用來傳遞額外的信息到任何類型的結構。

 

   void cv::setMouseCallback
    (
        const string& windowName,    //Handle used to identify window
        cv::MouseCallback on_mouse,    //Callback function
        void*                        //Additional parameters for callback fn.
    );


    第一個參數,回調函數作用的窗口名稱,只有事件在這個特定的窗口上時才能觸發回調。
    第二個參數,註冊的回調函數。
    第三個參數,可以在回調函數執行時給回調函數傳遞特定的信息。

 

#include<iostream>
#include<opencv2\highgui.hpp>
#include<opencv2\core.hpp>
#include<opencv2\imgproc.hpp>


void my_mouse_callback(int event, int x, int y, int flags, void*params);
cv::Rect box;
bool drawing_box = false;
void draw_box(cv::Mat& img, cv::Rect box)
{
	cv::rectangle
	(
		img,
		box.tl(),
		box.br(),
		cv::Scalar(0x00, 0x00, 0xff)
	);
}

int main()
{
	cv::Mat image(200, 200, CV_8UC3), tmp;


	box = cv::Rect(-1, -1, 0, 0);
	image = cv::Scalar::all(0);

	cv::namedWindow("Box Example");

	cv::setMouseCallback("Box Example", my_mouse_callback, (void*)&image);
	for (;;)
	{
		image.copyTo(tmp);
		cv::imshow("1", image);
		//std::cout << drawing_box << std::endl;
		if (drawing_box) draw_box(tmp, box);
		cv::imshow("Box Example", tmp);
		//cv::imshow("2", image);
		cv::waitKey(33);
	}
	return 0;
}

void my_mouse_callback(int event, int x, int y, int flags, void*params)
{
	cv::Mat& image = *(cv::Mat*)params;
	switch (event)
	{
	//鼠標動
	case cv::EVENT_MOUSEMOVE:
	{
		if (drawing_box)
		{
			box.width = x - box.x;
			box.height = y - box.y;
		}
		break;
	}
	//左鼠標按下
	case cv::EVENT_LBUTTONDOWN:
	{
		drawing_box = true;
		box = cv::Rect(x, y, 0, 0);
		break;
	}
	//左鼠標按下擡起
	case cv::EVENT_LBUTTONUP:
	{
		drawing_box = false;
		if (box.width < 0)
		{
			box.x += box.width;
			box.width *= -1;
		}
		if (box.height < 0)
		{
			box.y += box.height;
			box.height *= -1;
		}
		draw_box(image, box);
	}
	default:
		break;
	}
	
}


滑動條/滾動條 (slider/trackbar)

最初設計的目的就是在視頻播放幀中選擇特定幀。
在和父窗口使用時,需要給滑動條賦予一個特別的名字(通常是一個字符串),接下來將直接通過那個名字進行引用;
 

 int cv::createTrackbar(
    const string&         trackbarName,      // Handle used to identify trackbar
    const string&         windowName,      // Handle used to identify window
    int*                 value,              // Slider position gets put here
    int                     count,              // Total counts for slider at far right
    cv::TrackbarCallback onChange = NULL, // Callback function (option)
    void*                 param      = NULL  // Addition params for callback fn
    );


    第一個參數是滑動條的名稱,
    第二個參數是滑動條將要添加到父窗口的名稱,一旦滑動條創建好,它將被添加到窗口的頂部或底部。
        滑動條不會擋住任何已經在窗口中的圖像,只會讓窗口變大,窗口的名將作爲一個窗口的標記,至於滑動條上滑動鈕的
        的確切位置,由操作系統決定,一般都是最左邊。
    第三個參數 value,一個指向整數的指針,這個整數值會隨着滑動鈕的移動自動變化。
    第四個參數 count,是滑動條可以滑動的最大值。
    第五個參數 onChange,是一個指向回調函數的指針,當滑動鈕移動時,回調函數就會自動調用。
    第六個參數 param,可以是一個任何類型的指針,一旦回調函數執行,這個參數可以傳遞給回調函數
        的param參數,這樣不創建全局變量也可以處理滑動條事件。

    回調函數的特定形式,也就是說必須滿足一下定義:
  

  void your_trackbar_callback
    (
        int pos,                //Trackbar slider position
        void* param    = NULL   //Parameters from cv::serTrackbarCallback()
    );


    這個回調函數不是必須的,如果不需要直接賦值爲NULL,沒有回調函數,移動滑動鈕的唯一響應就是
    value指向的變量值得變化,

    //獲取滑動條的位置
    

int cv::getTrackbarPos
    (
        const string& trackName,    //Handle used to identify trackbar, label
        const string& windowName    //Handle used to identify window
    );


    //設置滑動條的位置
  

 void cv::setTrackbarPos
    (
        const string& trackName,    //Handle used to identify trackbar, label
        const string& windowName,    //Handle used to identify window
        int pos                        //Trackbar slider position
    );

 

#include<iostream>
#include<opencv2\highgui.hpp>
#include<opencv2\core.hpp>

int g_switch_value = 1;
void switch_off_function() { std::cout << "Puase" << std::endl; }
void switch_on_function() { std::cout << "Run" << std::endl; }

void switch_callback(int position, void*)
{
	if (position)
	{
		switch_on_function();
	}
	else
	{
		switch_off_function();
	}
}
char* videopath = "D:/Coder/vs/1_OpenCV/videoTest.mp4";
const cv::String nameWin = "Example";
int main()
{
	cv::Mat frame;
	cv::VideoCapture g_capture;
	g_capture.open(videopath);
	if (!g_capture.isOpened())
	{
		std::cout << "Error" << std::endl;
	}
	cv::namedWindow(nameWin, cv::WINDOW_AUTOSIZE);
	cv::createTrackbar(
		"Switch",
		nameWin,
		&g_switch_value,
		1,
		switch_callback
	);
	for (;;)
	{
		if (g_switch_value)
		{
			g_capture >> frame;
			if (frame.empty())
				break;
			cv::imshow(nameWin, frame);
		}
		if (cv::waitKey(33) == 27)
			break;
	}
	return 0;
}

 

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