cvSetImageROI函數(基于給定的矩形設定圖像的ROI(感興趣區域,region of interesting))
void cvSetImageROI(IplImage* image,CvRect rect) 參數: image 圖像頭,待處理圖像 rect ROI 感興趣區域矩形 cvResetImageROI函數(釋放基于給定的矩形設定圖像的ROI(感興趣區域,region of interesting)) void cvResetImageROI(IplImage* image) 參數: image 圖像頭,待處理圖像 cvcop函數(拷貝一個數組給另一個數組) 在使用這個函數之前,你必須用cvCreateImage()一類的函數先開一段記憶體,然後傳遞給dst。cvCopy會把src中的資料複制到dst的記憶體中。 copy隻會複制ROI區域,相當于函數cvCopy從輸入數組中複制標明的成分到輸出數組。 void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL ); 參數: src 輸入數組 dst 輸出數組 mask 操作掩碼是8比特單通道的數組,它指定了輸出數組中被改變的元素 cvCloneImage函數(複制圖像資料) 在使用函數之前,不用開辟記憶體。該函數會自己開一段記憶體,然後複制好image裡面的資料,然後把這段記憶體中的資料傳回給你。
clone是把所有的都複制過來,也就是說不論你是否設定Roi,Coi等影響copy的參數,clone都會原封不動的克隆過來。 IplImage* cvCloneImage( const IplImage* image ); 參數:image 輸入源圖像資料 傳回值: IplImage* 輸出圖像指針 注意:使用cvCloneImage()容易造成記憶體洩露,是以慎用。
cvCloneImage()每次使用時編譯器會配置設定新的記憶體空間,不會覆寫以前的内容,是以如果在循環中使用記憶體會迅速減小,每次用完都需要用cvRelease來釋放。
解決方法是使用cvCopy函數代替。
源代碼:
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
IplImage* src = 0;
IplImage* tmp = 0;
IplImage* tmp1 = 0;
IplImage* org = 0;
void on_mouse( int event, int x, int y, int flags, void* ustc)
{
static CvPoint pre_pt = {-1,-1};
static CvPoint cur_pt = {-1,-1};
CvFont font;
cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);//初始化字型
char temp[16];
if( (event == CV_EVENT_LBUTTONDOWN)&&(flags) )//滑鼠左鍵按下時
{
sprintf(temp,"(%d,%d)",x,y);//格式化字元串
pre_pt = cvPoint(x,y);//擷取目前點坐标值
cvPutText(src,temp, pre_pt, &font, cvScalar(0,0, 0, 255));//在圖像是列印字元
cvCircle( src, pre_pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );//在圖像上畫圓
cvShowImage( "src", src );
//cvCopy(src,tmp);//這句有沒有,就是單目标和多目标的問題
}
else if( (event == CV_EVENT_MOUSEMOVE) && (flags & CV_EVENT_LBUTTONDOWN))
{//滑鼠移動并且滑鼠左鍵按下
sprintf(temp,"(%d,%d)",x,y);//格式化字元串
cur_pt = cvPoint(x,y);//擷取目前點坐标值
cvPutText(src,temp, cur_pt, &font, cvScalar(0,0, 0, 255));//在圖像是列印字元
cvRectangle(src, pre_pt, cur_pt, cvScalar(0,255,0,0), 2, 8, 0 );//在圖像上畫矩形
cvShowImage( "src", src );
cvCopy(tmp,src);//将img複制到臨時圖像tmp上,用于實時顯示
}
else if( event == CV_EVENT_LBUTTONUP )
{//滑鼠左鍵彈起
sprintf(temp,"(%d,%d)",x,y);//字型格式化
cur_pt = cvPoint(x,y);//擷取目前點坐标值
cvPutText(src,temp, cur_pt, &font, cvScalar(0,0, 0, 255));//在圖像是列印字元
cvCircle( src, cur_pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );//在圖像上畫圓
cvRectangle( src, pre_pt, cur_pt, cvScalar(0,255,0,0), 2, 8, 0 );//在圖像上畫矩形
cvShowImage( "src", src );
/******************************************************************/
int width=abs(pre_pt.x-cur_pt.x); //兩點橫坐标差
int height=abs(pre_pt.y-cur_pt.y); //兩點縱坐标差
if(width==0 || height==0)
{ //兩者中有一個為零時銷毀視窗
cvDestroyWindow("dst");
return;
}
tmp1 = cvCreateImage(cvSize(width,height),org->depth,org->nChannels);
CvRect rect;
if(pre_pt.x<cur_pt.x && pre_pt.y<cur_pt.y)
{
rect=cvRect(pre_pt.x,pre_pt.y,width,height);
}
else if(pre_pt.x>cur_pt.x && pre_pt.y<cur_pt.y)
{
rect=cvRect(cur_pt.x,pre_pt.y,width,height);
}
else if(pre_pt.x>cur_pt.x && pre_pt.y>cur_pt.y)
{
rect=cvRect(cur_pt.x,cur_pt.y,width,height);
}
else if(pre_pt.x<cur_pt.x && pre_pt.y>cur_pt.y)
{
rect=cvRect(pre_pt.x,cur_pt.y,width,height);
}
cvSetImageROI(org,rect);//設定圖像的感興趣區域
cvCopy(org,tmp1); //将感興趣區域複制到tmp1
cvResetImageROI(org);//釋放圖像的感興趣區域
cvDestroyWindow("dst");//銷毀上次的顯示圖像
cvNamedWindow("dst",1);//建立視窗
cvShowImage("dst",tmp1); //顯示感興趣的圖像
cvSaveImage("dst.jpg",tmp1); //儲存感興趣圖像
/******************************************************************/
}
}
int main()
{
src=cvLoadImage("lena.jpg",1);//讀入圖像
tmp=cvCloneImage(src);//複制圖像到臨時圖像上
org=cvCloneImage(src);//儲存原始圖像
cvNamedWindow("src",1);//建立視窗
cvSetMouseCallback( "src", on_mouse, 0 );//注冊滑鼠響應回調函數
cvShowImage("src",src);//顯示圖像
cvWaitKey(0);//等待按鍵按下
cvDestroyAllWindows();//銷毀所有視窗
cvReleaseImage(&src);//釋放圖像
cvReleaseImage(&tmp);//釋放圖像
return 0;
}
效果圖: