(1)回调函数
OpenCV中setMouseCallback()创建了一个鼠标回调函数,每次在图像上单击鼠标左键再抬起的过程,都会分3次调用鼠标响应函数,并且响应顺序是:
1.左键单击按下;
2.左键单击抬起;
3.鼠标指针位置移动(即使原地单击,鼠标位置并没有移动);
函数声明如下:
CV_EXPORTS void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata = 0);函数参数介绍
const string& winname,windows视窗名称,对名为winname的视窗进行鼠标监控。
MouseCallback onMouse,鼠标响应处理函数,监听鼠标的点击,移动,松开,判断鼠标的操作类型,并进行响应的函数处理。
void* userdata = 0 鼠标响应处理函数的ID,与鼠标相应处理函数相匹配就行,暂时只用到默认为0的情况。
函数使用实例:
namedWindow("img");
setMouseCallback("img",on_mouse,0);
(2)响应处理函数
opencv2中,鼠标相应处理函数一般默认形参和返回参数,函数形式如下:
void on_mouse(int event,int x,int y,int flags,void *ustc)函数参数介绍:
int event,鼠标操作时间的整数代号,在opencv2中,event鼠标事件总共有10中,从0-9依次代表如下:
#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)坐标位置,窗口左上角默认为原点,向右为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不放事件
简单的实例如下:
#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp"
#include<iostream>
using namespace cv;
using namespace std;
void on_mouse(int event,int x,int y,int flags,void *ustc); //鼠标回调事件函数
int static times; //记录调用次数
int main(int argc,char*argv[])
{
Mat image=imread("e:\\kobe.jpg");
imshow("image",image);
setMouseCallback("image",on_mouse);
waitKey();
system("pause");
}
//鼠标回调函数
void on_mouse(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;
}
}
运行结果如下:
复杂一点的例子,用鼠标在一幅图上画线,程序如下:
#include<opencv2/opencv.hpp>运行结果如下:
#include<iostream>
using namespace std;
using namespace cv;
#define WINDOW "原图"
Mat g_srcImage,g_dstImage;
Point previousPoint;
bool P = false;
void On_mouse(int event, int x, int y, int flags, void*);
int main()
{
g_srcImage = imread("e://kobe.jpg");
imshow(WINDOW, g_srcImage);
setMouseCallback(WINDOW, On_mouse, 0);
waitKey(0);
return 0;
}
void On_mouse(int event, int x, int y, int flags, void*)
{
if (event == EVENT_LBUTTONDOWN)
{
previousPoint = Point(x, y);
}
else if (event == EVENT_MOUSEMOVE && (flags&EVENT_FLAG_LBUTTON))
{
Point pt(x, y);
line(g_srcImage, previousPoint, pt, Scalar(0,0,255), 2, 5, 0);
previousPoint = pt;
imshow(WINDOW, g_srcImage);
}
}
程序中用到了line()函数,后面单独总结一章:opencv基本绘图函数。
参考:
http://blog.csdn.net/xiaowei_cqu/article/details/8778976
http://www.eefocus.com/FthDesigner/blog/13-04/293698_9d0d0.html
http://blog.csdn.net/zhangping1987/article/details/51878636
http://blog.csdn.net/qq_29540745/article/details/52562101