如何在图像上用鼠标绘画矩形并且能够显示出来

来源:互联网 发布:淘宝小卖家怎么定位 编辑:程序博客网 时间:2024/05/22 00:45

前面的话依旧在学习OpenCV的道路慢慢摸索,道长且阻,但我心依旧。。。

今天学习了Highhui中提供的鼠标事件,且以实例来向大家展示如何使用鼠标事件

重点知识

鼠标事件响应采用回调函数的方式来处理,即,为了可以响应鼠标的各种事件,首先必须创建一个回调函数,是鼠标事件发生时OpenCV可以调用这个函数。创建这个函数后,需要在OpenCV中注册这个函数,以便特定窗口被触发鼠标事件以后,OpenCV可以正确调用这个函数。

回调函数

callback可以是满足指定输入参数以及返回参数类型的任何函数。

下面是回调函数必须符合的格式:

void CvMouseCallback(

int event,

int x,

int y,

int flags,

void *param);

第一个参数event必须为以下值中的一个:

事件名称                                           数值                   鼠标操作

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_LBUTTONBLCLK      7

CV_EVENT_RBUTTONBLCLK            8

CV_EVENT_MBUTTONBLCLK      9

第二个以及第三个参数会被设置成事件发生时鼠标位置的x,y坐标值。值得指出的是,这些坐标代表窗口中图像的像素坐标,与窗口大小无关。

第四个参数flags,每一位指定了在事件发生时的不同状态。例如,CV_EVENT_FLAG_SHIFTKEY的值为16(flags的第五位为1)。

鼠标事件标志                       数值

CV_EVENT_FLAG_LBUTTON                1

CV_EVENT_FLAG_RBUTTON 2

CV_EVENT_FLAG_MBUTTON  4

CV_EVENT_FLAG_CTRLKEY 8

CV_EVENT_FLAG_SHIFTKEY16

CV_EVENT_FLAG_ALTKEY32

最后一个参数是一个void* 指针,可以用来以任何结构方式传递额外的参数信息。

下面需要注册回调函数到OpenCV中,实现注册的函数式cvSetMouseCallback(),

void cvSetMouseCallback(

const char * window_name,

CvMouseCallback   on_mouse,

void * param=NULL

);

第一个参数指定了回调函数需要注册的窗口,也就是产生事件的窗口。只有在这个指定的窗口中触发的事件才会调用函数。第二个参数为回调函数。最后,第三个参数用来传递额外的信息给前面提到的void * param参数。

实例:如何在在图像上用鼠标绘画矩形并且能够显示出来

运行程序结果如下


源代码:

#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(0,0,0xff),1,8,0);}//根据Rect类型中的值在图像img绘制一个矩形int main(){box=cvRect(-1,-1,0,0);//初始化初值IplImage * image=cvCreateImage(cvSize(1000,700),IPL_DEPTH_8U,3);//创建一个宽1000、高700的像素类型为无符号8位整数3通道图像cvZero(image);//设置图像所有像素点全为黑IplImage *temp=cvCloneImage(image);//用图像image克隆出另一个图像tempcvNamedWindow("Box Example");//创建窗口cvSetMouseCallback("Box Example",my_mouse_callback,(void *)image);//注册函数while(1){cvCopyImage(image,temp);if(drawing_box) draw_box(temp,box);cvShowImage("Box Example",temp);if(cvWaitKey(10)==27)break;}//不停地把图像image Copy到图像temp中,然后在temp中根据drawing_box的值不停地画矩形并显示出来,使得在鼠标左键未松开时,画出的矩形能随着鼠标的移动动态的改变,每次停留的时间为10毫秒cvReleaseImage(&image);cvReleaseImage(&temp);cvDestroyWindow("Box Example");return 0;}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;}}//在鼠标在按住左键移动的时候能设置box的width和height。break;case CV_EVENT_LBUTTONDOWN:{drawing_box=true;box=cvRect(x,y,0,0);}//左键按住的时候设置能画矩形并且能设置矩形开始坐标break;case CV_EVENT_LBUTTONUP://左键松开{drawing_box=false;//设置为falseif(box.width<0&&box.height<0){box.x+=box.width;box.y+=box.height;box.height*=-1;box.width*=-1;}//如果矩形对角点的x,y都小于开始点的,则设置对角点为矩形的左上点,再修改宽高都为正值。else if(box.height<0){box.y +=box.height;box.height*=-1;}//如果矩形对角点的y小于开始点的,则将开始点的上边的点设置为左上点,修改高为正值。else if(box.width<0){box.x+=box.width;box.width*=-1;}//如果矩形对角点的x小于开始点的,则将开始点的左边的点设置为左上点,修改宽为正值。draw_box(image,box);//在松开左键的时候画矩形}break;}}//回调函数
                                             
0 0