#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;
}