您的位置:首页 > 其它

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

2013-12-11 19:12 316 查看
前面的话:依旧在学习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克隆出另一个图像temp
cvNamedWindow("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_bo
4000
x=false;//设置为false
if(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;
}
}//回调函数



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图形
相关文章推荐