#include <iostream> #include <cv.h> #include <highgui.h> using namespace cv; using namespace std; CvRect box; 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,0xff,0xff) //线条白色 ); } bool drawing_box = false; void my_mouse_callback(int event, int x, int y, int flags, void* param ) { IplImage *image = (IplImage*)param; //鼠标事件对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; 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 ); } break; default: break; } // case CV_EVENT_RBUTTONDOWN: //"触发右键按下事件" // } } int main() { cvNamedWindow( "Box namming" ); //用来建立窗口显示图像 void my_mouse_callback(int event, int x, int y, int flags, void* param ); IplImage *image = cvCreateImage(cvSize(200, 200), IPL_DEPTH_8U, 3); //定义了一个IplImage指针变量image,图像的大小是200×200,图像颜色深度8位,3通道图像。 cvZero( image );//全变黑:将图像中的每一个像素都置为0 cvSetMouseCallback( //鼠标事件发生 "Box namming", //指定窗口 my_mouse_callback, //回调函数名字注册到Box namming窗口 (void*) image //传入的函数的void* param 参数是(void*) image,//即咱们前面定义的IplImage* image ); /*void cvSetMouseCallback( const char* window_name, * CvMouseCallback on_mouse, * void* param=NULL ); * window_name 窗口的名字。 * on_mouse 指定窗口里每次鼠标事件发生的时候,被调用的函数指针。就是回调函数。 * param 用户定义的传递到回调函数的参数,也就是传递额外的信息给回调函数的void *param参数。 * 鼠标事件响应采用回调函数的方式来处理。即,为了能够响应鼠标点击事件,首先必须建立一个回调函数 * ,使鼠标点击事件发生时OpenCV能够调用这个函数。建立这个函数之后,须要在OpenCV中注册这个函数 * ,以便特定窗口被触发鼠标事件之后,OpenCV能够正确调用这个函数。 */ IplImage* temp = cvCloneImage( image ); // IplImage* temp = image; /*IplImage* cvCloneImage( const IplImage* image ); * 在使用函数以前,不用开辟内存。该函数会本身开一段内存, * 而后复制好image里面的数据,而后把这段内存中的数据返回给你。 * clone是把全部的都复制过来,也就是说不论你是否设置Roi,Coi等 * 影响copy的参数,clone都会原封不动的克隆过来。 * 在temp上画图——依然会触发鼠标事件,从而触发回调函数,从而实现了对图片image进行了操做。 * “在结束以前,为了实时显示所画的图形,将所画的图放在temp变量中,待画图结束时在image中存放这一次画图的最终结果。” * 就是说咱们之因此有一个temp,是由于若是没有temp,直接在image画,那么会显示过程,那么画一个矩形,一个大矩形由无数个小矩形组成,但咱们只要最终结果。 */ box = cvRect(-1, -1, 50, 50); /* * 它是OpenCV里面的基本数据类型 * 功能: 包含4个数据成员,x,y,width,height,经过定义矩形左上角坐标和矩形的宽和高来肯定一个矩形。 * OpenCV里面的基本数据类型 * 结构体功能: 经过矩形左上角坐标和矩形的宽和高来肯定一个矩形区域 * typedef struct CvRect * { * int x; // 方形的左上角的x-坐标 * int y; // 方形的左上角的y-坐标 * int width; // 宽 * int height; 高 * } */ while (1) { cvCopy( image, temp ); //cvCopyImage /*void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL ); * 若是设定了ROI等参数的时候,cvCopy只是复制被设定的区域,复制到一个和所设定参数相吻合的新的IplImage中。 * 在使用这个函数以前,你必须用cvCreateImage()一类的函数先开一段内存,而后传递给dst。cvCopy会把src中的数据复制到dst的内存中。 * copy就不同,只会复制ROI区域等。用clone复制以后,源图像在内存中消失后,复制的图像也变了,而用copy复制,源图像消失后,复制的图像不变。 */ if( drawing_box ) draw_box( temp, box ); cvShowImage( "Box namming", temp ); if( cvWaitKey( 15 )==27 ) break; } cvReleaseImage( &image ); cvReleaseImage( &temp ); cvDestroyWindow( "Box Example" ); return 0; }