1. 程式人生 > >【OpenCV】Mat與IplImage、cvMat之間的相互轉換

【OpenCV】Mat與IplImage、cvMat之間的相互轉換

原文博主的這篇真的非常清晰

OpenCV中Mat、CvMat和IplImage型別都可以代表和顯示影象。IplImage由CvMat派生,而CvMat由CvArr派生即CvArr -> CvMat -> IplImage,Mat型別則是C++版本的矩陣型別(CvArr用作函式的引數,無論傳入的是CvMat或IplImage,內部都是按CvMat處理)。
其中Mat型別側重於計算,數學性較高,OpenCV對Mat型別的計算也進行了優化;而CvMat和IplImage型別更側重於"影象",OpenCV對其中的影象操作(縮放、單通道提取、影象閾值操作等)進行了優化。很多時候需要三種類型的相互轉化,這裡簡要介紹一下。

========================CvMat和Mat間的轉化和拷貝========================
1、CvMat之間的複製

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

2、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 copy to b 

3、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 copy to b  

4、Mat轉CvMat

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


1、IplImage之間的複製
這個不贅述了,就是cvCopy與cvCloneImage使用區別,貼張網上的圖:


2、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);  

3、Mat轉IplImage

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

4、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);    //深拷貝  

5、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); //深拷貝  


最後注意:

1、Mat型別是自動記憶體管理,不需要顯式釋放(當然也可以手動呼叫release()方法強制Mat矩陣資料釋放);而CvMat則需要呼叫cvReleaseMat(&cvmat)來釋放,IplImage需要呼叫cvReleaseImage(&iplimage)來釋放。
2、建立CvMat矩陣時,第一個引數為行數,第二個引數為列數:
CvMat* cvCreateMat( int rows, int cols, int type );
3、建立IplImage影象時,CvSize第一個引數為寬度,即列數;第二個引數為高度,即行數:
IplImage* cvCreateImage(CvSize size, int depth, int channels );
CvSize cvSize( int width, int height );

4、IplImage內部buffer每行是按4位元組對齊的,CvMat沒有這個限制。