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);
}
}
處理的效果如下