利用opencv进行图像处理时,有时会用到鼠标进行用户交互,比如最为简单地,利用鼠标选中图像中的某个区域,将此区域返回给程序,进行后续的处理。opencv提供了鼠标事件的回调函数。回调函数即一种函数指针的使用。
函数原型为:
设置回调函数 void cvSetMouseCallback( const char* window_name, CvMouseCallback on_mouse, void* param=NULL );
参数:window_name 窗口名字 on_mouse 指定窗口中鼠标事件发生时被调用的函数指针 param可用来传递额外的参数信息
被回调函数 void (*CvMouseCallback )(int event, int x, int y, int flags, void* param);
参数:event 鼠标事件类型 x,y为图像坐标 flags表示发生时的状态; param由cvSetMouseCallback函数传入
使用方法为:
cvSetMouseCallback("窗口名",fun);
回调函数 void funt(int Event, int x, int y, int flags, void* param);
其中fun为自定义的鼠标事件函数名称。
鼠标事件分为三大类:1.点击(Click) 2.放开(Down) 3.滑动(move)
opencv中对鼠标事件进行了具体细分定义:
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 中键双击
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 <cv.h>
#include <highgui.h>
//左手画方.右手画圆
bool drawing_box=false;
bool drawing_circle=false;
CvRect box;
void draw_pin_box(IplImage *img, CvRect rect)
{
if(drawing_box)
cvRectangle(img,cvPoint(box.x,box.y),cvPoint(box.x+box.width,box.y+box.height),
cvScalar(255,0,255)
);
if(drawing_circle)
cvCircle( img, cvPoint(box.x,box.y),box.width,cvScalar(255,0,0),1, CV_AA, 0 );
}
void onMouse(int Event, int x, int y, int flags, void* param) //鼠标事件函数
{
IplImage* image= (IplImage*) param;
switch (Event)
{
case CV_EVENT_LBUTTONDOWN:
drawing_box=true;
drawing_circle=false;
box=cvRect(x,y,0,0);
break;
case CV_EVENT_RBUTTONDOWN:
drawing_box=false;
drawing_circle=true;
box=cvRect(x,y,0,0);
break;
case CV_EVENT_MOUSEMOVE:
if(drawing_box||drawing_circle)
{
box.width=x-box.x;
box.height=y-box.y;
}
break;
case CV_EVENT_LBUTTONUP:
case CV_EVENT_RBUTTONUP:
if(box.width<0)
{
box.x=box.x+box.width;
box.width*=-1;
}
if(box.height<0)
{
box.y+=box.height;
box.height*=-1;
}
draw_pin_box(image,box);
drawing_box=false;
drawing_circle=false;
break;
default:
break;
}
}
int main()
{
box=cvRect(-1,-1,0,0);
IplImage* pic=cvLoadImage("summ.bmp",1);
cvNamedWindow("mousecase",1);
cvSetMouseCallback("mousecase",onMouse,(void*)pic);
while(1){
cvShowImage("mousecase",pic);
if(cvWaitKey(15)==27) break;
}
cvReleaseImage(&pic);
cvDestroyWindow("mousecase");
return 0;
}
效果图: