Opencv——setMouseCallback

用戶通過鼠標對圖像視窗最常見的操作有:

1. 左鍵單擊按下

2. 左鍵單擊擡起

3. 左鍵按下拖動

4. 鼠標指針位置移動


單次單擊操作響應事件及順序

Opencv中setMouseCallback()創建了一個鼠標回調函數,每次在圖像上單擊鼠標左鍵再擡起的過程,都會分3次調用鼠標響應函數,並且響應順序是:

1.左鍵單擊按下;

2.左鍵單擊擡起;

3.鼠標指針位置移動(即使原地單擊,鼠標位置並沒有移動);


可以編碼驗證一下回調函數的這個調用機制:

#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
#include<iostream>
using namespace cv;
using namespace std;
void OnMouseAction(int event,int x,int y,int flags,void *ustc); //鼠標回調事件函數
int static times; //記錄調用次數
int main(int argc,char*argv[])
{
Mat image=imread(argv[1]);
imshow("image",image);
setMouseCallback("image",OnMouseAction);
waitKey();
system("pause");
}
//*******************************************************************//
//鼠標回調函數
void OnMouseAction(int event,int x,int y,int flags,void *ustc)
{
times++;
cout<<"第 "<<times<<" 次回調鼠標事件"<<endl;
if(event==CV_EVENT_MOUSEMOVE)
{
cout<<"觸發鼠標移動事件"<<endl;
}
if(event==CV_EVENT_LBUTTONDOWN)
{
cout<<"觸發左鍵按下事件"<<endl;
}
if(event==CV_EVENT_LBUTTONUP)
{
cout<<"觸發左鍵擡起事件"<<endl;
}
if(event==CV_EVENT_RBUTTONDOWN)
{
cout<<"觸發右鍵按下事件"<<endl;
}
if(event==CV_EVENT_RBUTTONUP)
{
cout<<"觸發右鍵擡起事件"<<endl;
}
if(event==CV_EVENT_LBUTTONDBLCLK)
{
cout<<"觸發左鍵雙擊事件"<<endl;
}
if(event==CV_EVENT_RBUTTONDBLCLK)
{
cout<<"觸發右鍵雙擊事件"<<endl;
}
}



前3次調用是在左鍵單擊前鼠標指針在圖像窗口移動造成的。不移動位置,單擊左鍵,觸發了第4次調用,紅色框框內的就是一個完整的鼠標按下再擡起的調用過程:

第一次傳入的event事件是左鍵單擊“CV_EVENT_LBUTTONDOWN”;

第二次傳入的event事件是左鍵擡起“CV_EVENT_LBUTTONUP”;

第三次傳入的event事件是鼠標移動“CV_EVENT_MOUSEMOVE”,這時候鼠標物理位置其實並沒有移動;


setMouseCallback()函數

瞭解了鼠標回調函數的調用機制後再來看一下創建回調函數的函數setMouseCallback();

原型:

void setMouseCallback(const string& winname,     //圖像視窗名稱
MouseCallback onMouse,     //鼠標響應函數,監視到鼠標操作後調用並處理相應動作
void* userdata = 0       //鼠標響應處理函數的ID,識別號
);

OnMouseAction()響應函數

鼠標事件回調函數onMouse按照固定格式創建響應函數:

void OnMouseAction(int event,int x,int y,int flags,void *ustc) 

event事件代表了鼠標的各種操作,詳細看一下各個event事件:

Event:
#define CV_EVENT_MOUSEMOVE 0 //滑動
#define CV_EVENT_LBUTTONDOWN 1 //左鍵點擊
#define CV_EVENT_RBUTTONDOWN 2 //右鍵點擊
#define CV_EVENT_MBUTTONDOWN 3 //中鍵點擊
#define CV_EVENT_LBUTTONUP 4 //左鍵放開
#define CV_EVENT_RBUTTONUP 5 //右鍵放開
#define CV_EVENT_MBUTTONUP 6 //中鍵放開
#define CV_EVENT_LBUTTONDBLCLK 7 //左鍵雙擊
#define CV_EVENT_RBUTTONDBLCLK 8 //右鍵雙擊
#define CV_EVENT_MBUTTONDBLCLK 9 //中鍵雙擊


int x,int y,代表鼠標位於窗口的(x,y)座標位置,即Point(x,y);
int flags,代表鼠標的拖拽事件,以及鍵盤鼠標聯合事件,共有32種事件:


flags:
#define CV_EVENT_FLAG_LBUTTON 1 //左鍵拖曳
#define CV_EVENT_FLAG_RBUTTON 2 //右鍵拖曳
#define CV_EVENT_FLAG_MBUTTON 4 //中鍵拖曳
#define CV_EVENT_FLAG_CTRLKEY 8 //(8~15)按Ctrl不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16 //(16~31)按Shift不放事件
#define CV_EVENT_FLAG_ALTKEY 32 //(32~39)按Alt不放事件


函數指針 void *ustc標識了所響應的事件函數,相當於自定義了一個OnMouseAction()函數的ID。

簡單應用:記錄鼠標按下時座標和鼠標擡起時座標,分別做Line、Rectangle、Circle



#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
#include<iostream>
using namespace cv;
using namespace std;
void OnMouseAction(int event,int x,int y,int flags,void *ustc); //鼠標回調事件函數
int static times; //記錄調用次數
int rowsBegin,rowsEnd;
int colsBegin,colsEnd;
Mat image;
int main(int argc,char*argv[])
{
image=imread(argv[1]);
imshow("image",image);
setMouseCallback("image",OnMouseAction);
}
//*******************************************************************//
//鼠標回調函數
void OnMouseAction(int event,int x,int y,int flags,void *ustc)
{
if(event==CV_EVENT_MOUSEMOVE)
{
cout<<"觸發鼠標移動事件"<<endl;
}
if(event==CV_EVENT_LBUTTONDOWN)
{
rowsBegin=y;
colsBegin=x;
cout<<"觸發左鍵按下事件"<<endl;
}
if(event==CV_EVENT_LBUTTONUP)
{
rowsEnd=y;
colsEnd=x;
line(image,Point(colsBegin,rowsBegin),Point(colsEnd,rowsEnd),Scalar(255,0,0),2,8,0);
rectangle(image,Rect(colsBegin,rowsBegin,colsEnd-colsBegin,rowsEnd-rowsBegin),Scalar(0,255,0),2,8,0);
circle(image,Point((colsEnd+colsBegin)/2,(rowsEnd+rowsBegin)/2),rowsEnd-rowsBegin,Scalar(0,0,255),2,8,0);
imshow("image",image);
cout<<"觸發左鍵擡起事件"<<endl;
}
if(event==CV_EVENT_RBUTTONDOWN)
{
cout<<"觸發右鍵按下事件"<<endl;
}
if(event==CV_EVENT_RBUTTONUP)
{
cout<<"觸發右鍵擡起事件"<<endl;
}
if(event==CV_EVENT_LBUTTONDBLCLK)
{
cout<<"觸發左鍵雙擊事件"<<endl;
}
if(event==CV_EVENT_RBUTTONDBLCLK)
{
cout<<"觸發右鍵雙擊事件"<<endl;
}
}

發佈了28 篇原創文章 · 獲贊 18 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章