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