最近两天学习了一下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;
Mat srcImg,tmpImg, MidImg;
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);
}
}
处理的效果如下