项目需要,最近在IplImage,CvMat ,Mat,CvArr之间转来转去;网上资料很多,版本有点混乱,整理一下,资源共享。
派生关系:CvArr -> CvMat -> IplImage
IpImage 和CvMat 是C语言的struct。而cv::Mat 是c++中的结构。
现在的OpenCV要向Matlab靠拢,比如Mat常用函数imshow、imread、imwrite等和Matlab中函数一致;Mat类型侧重于计算,数学性较高,于是OpenCV对Mat类型的计算进行了优化,帮助管理内存分配,这样就不用自己create和release了,比使用CvMat 要方便。
而CvMat和IplImage类型更侧重于"图像"操作,CvArr及其子类常用函数比如cvLoadImage(),cvShowImage()等,和Mat常用函数不同。
1.1IplImage转CvMat
//opencv3.x版本:
//cvGetMat函数,深拷贝
IplImage* img;
CvMat temp;
CvMat* mat = cvGetMat(img, &temp);
//cvConvert函数,深拷贝
CvMat *mat = cvCreateMat(img->height,img->width, CV_64FC3);
cvConvert(img, mat);
1.2CvMat转IplImage
//cvGetImage函数,深拷贝
CvMat M;
IplImage* img =cvCreateImageHeader(M.size(), M.depth(), M.channels());
cvGetImage(&M, img);
// cvConvert函数,深拷贝
CvMat M;
IplImage* img = cvCreateImage(M.size(),M.depth(), M.channels());
cvConvert(&M, img);
2.1IplImage转Mat
//opencv2.x版本:
//使用Mat的构造函数,默认情况下copyData为false
Mat::Mat(const IplImage* img, boolcopyData=false);
//当参数copyData为true时,则为深拷贝(复制整个图像数据)
Mat M(srcImg, true);
IplImage* srcImg;
//以下三种效果一致,均为浅拷贝
Mat M(srcImg);
Mat M(srcImg, false);
Mat M = srcImg;
//opencv3.x版本:
Mat m(src); //不复制内容
IplImage* srcImg;
Mat m = cvarrToMat(srcImg,true);
2.2Mat转IplImage
//低版本
Mat img;
IplImage *src;
src=&IplImage(img);
Mat m;
IplImage* dstImg = cvCloneImage(&(IplImage)m);
//浅拷贝
Mat M;
IplImage img = M;
IplImage img = IplImage(M);
3.1CvMat转Mat
//opencv2.x版本:
//使用Mat的构造函数,默认copyData为false
Mat::Mat(const CvMat* m, boolcopyData=false);
//当参数copyData为true时,则为深拷贝
Mat b = Mat(a, true);
CvMat* a;
//以下三种效果一致,均为浅拷贝
Mat b(a);
Mat b(a, false);
Mat b = a;
3.2Mat转CvMat
//浅拷贝
Mat a;
CvMat b = a;
//深拷贝
Mat a;
CvMat *b;
CvMat temp = a;
cvCopy(&temp, b);
4.(多通道)Mat, IplImage, CvMat的元素获取
IplImage:
//i is the index of rows
//j is the index of cols
//c is the index of channel
((uchar*)pImg->imageData+i*pImg->widthStep)[j*3+c]
CV_IMAGE_ELEM(pImg,uchar,i,3*j+c)
CvMat:
CV_MAT_ELEM(cvmat,uchar,i,3*j+c) ;
Mat:
Mat m;
int h = m.rows; int w = m.cols;
int nc = m.channels();
for (int i = 0;i
{
for(intj = 0;j
{
Vec3b&elem = m.at
for(int c = 0; c
{
ucharuc = elem[c] ;//Mat(i,j) of channel c
}
}
}
5.一些区别:
1.Mat类型是自动内存管理,不需要显式释放;而CvMat则需要调用cvReleaseMat(&cvmat)来释放,IplImage需要调用cvReleaseImage(&iplimage)来释放。
2.建立IplImage图像时,CvSize第一个参数为宽度,即列数;第二个参数为高度,即行数:IplImage*cvCreateImage(CvSize size, int depth, int channels );
CvSize cvSize( int width, int height );
3.建立CvMat矩阵时,第一个参数为行数,第二个参数为列数:
CvMat* cvCreateMat( int rows, int cols, int type );
4.IplImage内部buffer每行是按4字节对齐的,CvMat没有这个限制。
参考:
Mat, IplImage, CvMat, Cvarr关系及元素获取
http://blog.csdn.net/abcjennifer/article/details/17640195
OpenCV中矩阵类详解之三:CvMat,Mat和IplImage之间的转化和拷贝
http://blog.csdn.net/holybin/article/details/17711013
IpImage 与 cvImage, cvMat 与 cv::Mat
http://blog.sina.com.cn/s/blog_79bb01d00101ao59.html
OpenCV 2.4.3 Cheat Sheet学习(一)
http://blog.sina.com.cn/s/blog_8924265b0101fblj.html