Mat, IplImage, CvMat, Cvarr关系及元素获取

来源:互联网 发布:自己知为知己可以 编辑:程序博客网 时间:2024/06/06 00:28

自己目前正打算整理opencv数据结构之间关系,寻寻觅觅之间,发现这篇博文很全面,总结得很好,故转之。红色部分不对,自己已修改!

原文地址:http://blog.csdn.net/abcjennifer/article/details/17640195





1、Mat, IplImage, CvMat, CvArr的关系:

1. opencv文档中明确声明,CvMat已经过时了(CvMat is now obsolete, consider using Mat instead)不建议用;

2. 派生关系:CvArr -> CvMat -> IplImage

3. Mat用的一套东西是imread,imshow等,有别于CvArr及其子类的cvLoadImage(),cvShowImage()...




2. 相互转换

所有代码已经过测试,但是这里我就示意一下,真正写的时候不要忘记初始化转化过去的变量。


2.1 Mat与IplImage相互转换

IplImage* src;

某文章说,转换应该是Mat m(src); 而这不会复制内容,真正能复制内容的是:

Mat -> IplImage:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. Mat m;  
  2. IplImage* transIplimage = cvCloneImage(&(IplImage) m);  


IplImage -> Mat

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. IplImage* transIplImage;  
  2. Mat m = cvarrToMat(transIplImage,true);  


2.2 CvMat与IplImage相互转换

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. IplImage* transIplImage;  
  2. CvMat* cvmat;  
  3. cvGetMat(transIplImage,cvmat);  
  4. cvGetImage(cvmat,transIplImage);  



3. (多通道)Mat, IplImage, CvMat的元素获取

单通道的网上很多,这里只写多通道:

3.1 IplImage

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. //i is the index of rows  
  2. //j is the index of cols  
  3. //c is the index of channel  
  4. ((uchar*)pImg->imageData+i*pImg->widthStep)[j*3+c]  
  5. CV_IMAGE_ELEM(pImg,uchar,i,3*j+c)   


3.2 Mat





本人这几天都在探索如何访问Mat三通道中的数据,发现原作者提供的如下代码不对。


[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. Mat m;  
  2. int h = m.rows; int w = m.cols;  
  3. int nc = m.channels();    
  4. for (int i = 0;i<h;i++)  
  5. {  
  6.     for(int j = 0;j<w;j++)  
  7.     {  
  8.         Vec3b& elem = m.at<Vec3b>(i,j);  
  9.         for (int c = 0; c<nc; c++)  
  10.         {  
  11.             uchar uc = elem[c] ;//Mat(i,j) of channel c  
  12.         }  
  13.     }  
  14. }  

后来经过本人的跋山涉水,发现正确的访问三通道Mat数据的代码如下:

 


定位像素不能使用int,而是应该使用size_t,前车之鉴,希望大家不要重蹈覆辙,这两天的努力没有白费,马克一下,哈哈~


3.3 CvMat

CV_MAT_ELEM(cvmat,uchar,i,3*j+c) 



4. 验证获取元素代码(Mat转IplImage)

此代码只用于验证多通道元素获取没有错误,具体用的时候最好还是用opencv直接给的吧(见第3小节)

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. IplImage* cvcvt_mat2IplImage(Mat m)  
  2. {  
  3.     int h = m.rows; int w = m.cols;  
  4.     int nc = m.channels();  
  5.     IplImage* pImg = cvCreateImage(cvSize(w,h),8,nc);  
  6.       
  7.     for (int i = 0;i<h;i++)  
  8.     {  
  9.         for(int j = 0;j<w;j++)  
  10.         {  
  11.             Vec3b& elem = m.at<Vec3b>(i,j);  
  12.             for (int c = 0; c<nc; c++)  
  13.             {  
  14.                 //以下两种都可以  
  15.                 //((uchar*)pImg->imageData+i*pImg->widthStep)[j*3+c] =  elem[c];  
  16.                 CV_IMAGE_ELEM(pImg,uchar,i,3*j+c) = elem[c];  
  17.             }  
  18.         }  
  19.     }  
  20.     return pImg;  
  21. }  





0 0
原创粉丝点击