在实际的图像处理当中,很多时候需要我们人为的选择感兴趣的区域(ROI),比如在图像中框出目标物体等。其实之前有不少地方都有用到这种鼠标事件的响应功能,感觉挺有用的,虽然不是自动选择物体,现在单独拿出来总结一下。
为了可以响应鼠标事件,首先必须创建一个回调函数,该函数使得点击鼠标时,在opencv中注册回调函数,就可以可以调用该回调函数了。回调函数的格式为:
void CvMouseCallback( int event, int x, int y, int flags, void *param);
参数意义:
第一个参数event的值为:
第二、三个参数x、y是事件发生时 鼠标位置的x,y坐标值(图像的像素坐标,与窗口大小无关)。
第四个参数flags,每一位指定了在事件发生时的不同状态:
最后一个参数是一个void指针,可以用来以任何结构方式传递额外的参数信息。
在opencv中注册回调函数:
void cvSetMouseCallback(const char*window_name,
CvMouseCallback on_mouse,
void * param = NULL);
第一个参数:指定回调函数需要注册到的窗口,即事件发生的窗口;
第二个参数:回调函数;
第三个参数:用来传递额外的信息给前面提到的void *param参数。
下面给出书上的利用鼠标画矩形的源码:
#include<iostream>
using namespace std;
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
void my_mouse_callback( //回调函数的声明,而回调函数也是需要这种参数格式
int event,int x,int y,int flags,void * param
);
CvRect box;
bool drawing_box = false;
void draw_box(IplImage *img,CvRect rect){
cvRectangle( //画一个矩形
img,
cvPoint(box.x,box.y),
cvPoint(box.x+box.width,box.y+box.height),
cvScalar(0xff,0x00,0x00)
);
}
int main()
{
box = cvRect(-1,-1,0,0);
IplImage * image = cvCreateImage( cvSize(500,500), IPL_DEPTH_8U, 3);
cvZero(image);
IplImage *temp = cvCloneImage( image );
cvNamedWindow("Box Example");
cvSetMouseCallback( "Box Example", my_mouse_callback, (void *)image );
while( 1 )
{
cvCopyImage(image,temp);
if(drawing_box)draw_box(temp,box);//这里是在鼠标移动的时候矩阵,能够随鼠标的移动而移动
//注意到这里有两个图像,现在是先把临时的矩阵(大小)还在变化的矩阵写在temp图像上
cvShowImage("Box Example",temp);//显示temp图像的情况
if( cvWaitKey( 15 )==27 )break;
}
cvReleaseImage(&image);
cvReleaseImage(&temp);
cvDestroyWindow("Box Example");
}
void my_mouse_callback(int event,int x,int y,int flags,void * param )
{
IplImage *image = (IplImage *)param;
switch(event){
case CV_EVENT_MOUSEMOVE: //从左往右,从上往下移动鼠标
{
if(drawing_box)
{ //记录鼠标按下去后并且移动的偏移量
box.width=x-box.x;
box.height=y-box.y;
}
}
break;
case CV_EVENT_LBUTTONDOWN:
{
drawing_box = true; //drawing_box=true 表示鼠标按下去了
box = cvRect(x,y,0,0);
}
break;
case CV_EVENT_LBUTTONUP:
{
drawing_box = false;
if( box.width < 0 ) //从右往左移动
{
box.x += box.width;
box.width *= -1;
}
if( box.height < 0 ) //从下往上移动
{
box.y += box.height;
box.height *= -1;
}
draw_box(image, box);//这时就把已经确定的矩阵写到image图像里
}
break;
}
}
reference:学习opencv中文版