1. 程式人生 > >影象型別轉換與拷貝

影象型別轉換與拷貝

//CvMat之間的複製
//注意:深拷貝 - 單獨分配空間,兩者相互獨立
CvMat* a;
CvMat* b = cvCloneMat(a);    //copy a to b

//Mat之間的複製
//注意:淺拷貝 -  不復制資料只建立矩陣頭,資料共享(更改a,b,c的任意一個都會對另外2個產生同樣的作用)
Mat a;
Mat b = a; //a "copy" to b
Mat c(a); //a "copy" to c
 
//注意:深拷貝
Mat a;
Mat b = a.clone(); //a copy to b
Mat c;
a.copyTo(c); //a copy to c

// IplImage之間的複製
CVAPI(void) cvCopy(const CvArr* src,const CvArr* dst,const CvArr* mask,CV_DEFAULT(NULL));
//只複製ROI區域影象,dst先需要用cvCreateImage()開闢一段記憶體

CVAPI(IplImage*) cvCloneImage(const IplImage* image);
//複製影象所有資料,包括ROI引數等 不需要開闢記憶體,函式會自己開一段記憶體。

//首先設定影象ROI區域,然後建立新的影象記憶體,通過cvCopy函式拷貝,注意,拷貝的是影象的ROI區域。

cvSetImageROI(img3,CvRect(r.x,r.y,r.width,r.height)); //設定感興趣區域

//新建一個IplImage dst_img 大小與設定感興趣區域一致
dst_img= cvCreateImage(CvSize(r.width,r.height), IPL_DEPTH_8U,img3->nChannels);
cvCopy(img3,dst_img,0);  //複製感興趣區域到dst_img 中
cvResetImageROI(img3);  //重置感興趣區域

//也可以設定影象ROI區域然後拷貝整個影象,包括影象的ROI區域資訊屬性,採用cvCloneImage() 函式,但該函式會出現較大 

//的記憶體洩露,雖然可以釋放,但因程式複雜不知道在那裡釋放,因為它每次拷貝是製作影象的完整拷貝包括頭、ROI和資料。

//每次使用時編譯器會分配新的記憶體空間,不會覆蓋以前的內容。

//cvCopy函式使用前,必須先對目的影象進行記憶體分配,即使用cvCreateImage函式,否則無法執行。

pImg = cvCreateImage(cvSize(IMGWIDHT,IMGHEIGHT),IPL_DEPTH_8U, 3);

void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );

//在使用這個函式之前,你必須用cvCreateImage()一類的函式先開一段記憶體,然後傳遞給dst。cvCopy會把src中的資料複製到

//dst的記憶體中。

//cvCloneImage的原型是:

IplImage* cvCloneImage( const IplImage* image );

//在使用函式之前,不用開闢記憶體。該函式會自己開一段記憶體,然後複製好image裡面的資料,然後把這段記憶體中的資料返回給

//你。而clone是把所有的都複製過來,也就是說不論你是否設定Roi,Coi等影響copy的引數,clone都會原封不動的克隆過來。

//copy就不一樣,只會複製ROI區域等。即用cvCopy複製之後,源影象在記憶體中消失後,複製的影象也變了,而用cvCloneImage

//複製,源影象消失後,複製的影象不變。

cvCopy(pSrcImg,pImg,NULL); 

pImg = cvCloneImage(pSrcImg);

 

//CvMat轉Mat.
//使用Mat的建構函式:Mat::Mat(const CvMat* m, bool copyData=false); 預設情況下copyData為false
CvMat* a;
//注意:以下三種效果一致,均為淺拷貝
Mat b(a); //a "copy" to b
Mat b(a, false); //a "copy" to b
Mat b = a; //a "copy" to b 
//注意:當將引數copyData設為true後,則為深拷貝(複製整個影象資料)
Mat b = Mat(a, true); //a clone to b

//Mat轉CvMat
//注意:淺拷貝
Mat a;
CvMat b = a; //a "copy" to b 
//注意:深拷貝
Mat a;
CvMat *b;
CvMat temp = a; //轉化為CvMat型別,而不是複製資料
cvCopy(&temp, b); //真正複製資料

//IplImage轉Mat
//使用Mat的建構函式:Mat::Mat(const IplImage* img, bool copyData=false);    預設情況下copyData為false
IplImage* srcImg = cvLoadImage("Lena.jpg");
//注意:以下三種效果一致,均為淺拷貝
Mat M(srcImg);
Mat M(srcImg, false);
Mat M = srcImg;
 
//注意:當將引數copyData設為true後,則為深拷貝(複製整個影象資料)
Mat M(srcImg, true);

//Mat轉IplImage
//注意:淺拷貝 - 同樣只是建立影象頭,而沒有複製資料
Mat M;
IplImage img = M;
IplImage img = IplImage(M);

//IplImage轉CvMat
//法一:cvGetMat函式
IplImage* img;
CvMat temp;
CvMat* mat = cvGetMat(img, &temp);    //深拷貝
//法二:cvConvert函式
CvMat *mat = cvCreateMat(img->height, img->width, CV_64FC3);    //注意height和width的順序
cvConvert(img, mat);    //深拷貝

//CvMat轉IplImage
//法一:cvGetImage函式
CvMat M;
IplImage* img = cvCreateImageHeader(M.size(), M.depth(), M.channels());
cvGetImage(&M, img);    //深拷貝:函式返回img
//也可寫成
CvMat M;
IplImage* img = cvGetImage(&M, cvCreateImageHeader(M.size(), M.depth(), M.channels()));
//法二:cvConvert函式
CvMat M;
IplImage* img = cvCreateImage(M.size(), M.depth(), M.channels());
cvConvert(&M, img);    //深拷貝

//影象記憶體釋放

Mat是記憶體自動管理,無需手動釋放記憶體,可以手動採用cvRelease()釋放,cvMat* 需手動釋放,cvReleaseMat(&m),IplImage* 需手動釋放,cvReleaseImage(&img);建立CvMat矩陣時,第一個引數為行數,第二個引數為列數:
CvMat* cvCreateMat( int rows, int cols, int type );
建立IplImage影象時,CvSize第一個引數為寬度,即列數;第二個引數為高度,即行數:
IplImage* cvCreateImage(CvSize size, int depth, int channels );
CvSize cvSize( int width, int height );
IplImage內部buffer每行是按4位元組對齊的,CvMat沒有這個限制。