鼠標事件
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;
}