[轉帖] CvMat,Mat和IplImage之間的轉化和拷貝


 

原文地址: http://blog.csdn.net/holybin/article/details/17711013

在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之間的復制

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

2、Mat之間的復制

  1. //注意:淺拷貝 -  不復制數據只創建矩陣頭,數據共享(更改a,b,c的任意一個都會對另外2個產生同樣的作用)  
  2. Mat a;  
  3. Mat b = a; //a "copy" to b  
  4. Mat c(a); //a "copy" to c  
  5.   
  6. //注意:深拷貝  
  7. Mat a;  
  8. Mat b = a.clone(); //a copy to b  
  9. Mat c;  
  10. a.copyTo(c); //a copy to c  

3、CvMat轉Mat

  1. //使用Mat的構造函數:Mat::Mat(const CvMat* m, bool copyData=false); 默認情況下copyData為false  
  2. CvMat* a;  
  3. //注意:以下三種效果一致,均為淺拷貝  
  4. Mat b(a);   //a "copy" to b  
  5. Mat b(a, false);    //a "copy" to b  
  6. Mat b = a;  //a "copy" to b  
  7.   
  8. //注意:當將參數copyData設為true后,則為深拷貝(復制整個圖像數據)  
  9. Mat b = Mat(a, true); //a copy to b  

4、Mat轉CvMat

  1. //注意:淺拷貝  
  2. Mat a;  
  3. CvMat b = a; //a "copy" to b  
  4.   
  5. //注意:深拷貝  
  6. Mat a;  
  7. CvMat *b;  
  8. CvMat temp = a; //轉化為CvMat類型,而不是復制數據  
  9. cvCopy(&temp, b); //真正復制數據  


========================IplImage與上述二者間的轉化和拷貝========================
1、IplImage之間的復制
這個不贅述了,就是cvCopy與cvCloneImage使用區別,貼張網上的圖:

2、IplImage轉Mat

  1. //使用Mat的構造函數:Mat::Mat(const IplImage* img, bool copyData=false);    默認情況下copyData為false  
  2. IplImage* srcImg = cvLoadImage("Lena.jpg");  
  3. //注意:以下三種效果一致,均為淺拷貝  
  4. Mat M(srcImg);  
  5. Mat M(srcImg, false);  
  6. Mat M = srcImg;  
  7.   
  8. //注意:當將參數copyData設為true后,則為深拷貝(復制整個圖像數據)  
  9. Mat M(srcImg, true);  

3、Mat轉IplImage

  1. //注意:淺拷貝 - 同樣只是創建圖像頭,而沒有復制數據  
  2. Mat M;  
  3. IplImage img = M;  
  4. IplImage img = IplImage(M);  

4、IplImage轉CvMat

  1. //法一:cvGetMat函數  
  2. IplImage* img;  
  3. CvMat temp;  
  4. CvMat* mat = cvGetMat(img, &temp);  //深拷貝  
  5. //法二:cvConvert函數  
  6. CvMat *mat = cvCreateMat(img->height, img->width, CV_64FC3);  //注意height和width的順序  
  7. cvConvert(img, mat);    //深拷貝  

5、CvMat轉IplImage

  1. //法一:cvGetImage函數  
  2. CvMat M;  
  3. IplImage* img = cvCreateImageHeader(M.size(), M.depth(), M.channels());  
  4. cvGetImage(&M, img);    //深拷貝:函數返回img  
  5. //也可寫成  
  6. CvMat M;  
  7. IplImage* img = cvGetImage(&M, cvCreateImageHeader(M.size(), M.depth(), M.channels()));  
  8. //法二:cvConvert函數  
  9. CvMat M;  
  10. IplImage* img = cvCreateImage(M.size(), M.depth(), M.channels());  
  11. 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沒有這個限制。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM