1、IplImage --> Mat
转换函数:
//! converts old-style IplImage to the new matrix; the data is not copied by default
Mat(const IplImage* img, bool copyData=false);
该函数是Mat的一个
构造函数,其主要功能是将IplImage格式的图像转换为Mat格式;bool类型的参数copyData标志是否需要复制图像数据,若为false,则不复制数据,即两种格式的图像共享内存;若为true,则直接复制数据,可以理解为转换后得到的Mat与前面的IplImage不再有关系,对mat的修改将不会再影响到IplImage。这地方数据的复制,还可以结合Mat的赋值操作费“=”与clone()、copy()来理解,通过“=”关联的两个Mat共享数据,当修改其中一个的数据时,会影响到另一个;通过clone和copy关联的两个Mat并不共享数据。
函数实现:
Mat::Mat(const IplImage* img, bool copyData) : size(&rows)
{
initEmpty();
if( !img )
return;
dims = 2;
CV_DbgAssert(CV_IS_IMAGE(img) && img->imageData != 0);
int imgdepth = IPL2CV_DEPTH(img->depth);
size_t esz;
step[0] = img->widthStep;
if(!img->roi)
{
CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL);
flags = MAGIC_VAL + CV_MAKETYPE(imgdepth, img->nChannels);
rows = img->height; cols = img->width;
datastart = data = (uchar*)img->imageData;
esz = CV_ELEM_SIZE(flags);
}
else
{
CV_Assert(img->dataOrder == IPL_DATA_ORDER_PIXEL || img->roi->coi != 0);
bool selectedPlane = img->roi->coi && img->dataOrder == IPL_DATA_ORDER_PLANE;
flags = MAGIC_VAL + CV_MAKETYPE(imgdepth, selectedPlane ? 1 : img->nChannels);
rows = img->roi->height; cols = img->roi->width;
esz = CV_ELEM_SIZE(flags);
data = datastart = (uchar*)img->imageData +
(selectedPlane ? (img->roi->coi - 1)*step*img->height : 0) +
img->roi->yOffset*step[0] + img->roi->xOffset*esz;
}
datalimit = datastart + step.p[0]*rows;
dataend = datastart + step.p[0]*(rows-1) + esz*cols;
flags |= (cols*esz == step.p[0] || rows == 1 ? CONTINUOUS_FLAG : 0);
step[1] = esz;
if( copyData )
{
Mat m = *this;
release();
if( !img->roi || !img->roi->coi ||
img->dataOrder == IPL_DATA_ORDER_PLANE)
m.copyTo(*this);
else
{
int ch[] = {img->roi->coi - 1, 0};
create(m.rows, m.cols, m.type());
mixChannels(&m, 1, this, 1, ch, 1);
}
}
}
函数调用方式:
// 此处说明如何转换,不检测图像是否加载成功
IplImage* img = cvLoadImage("Lena.jpg");
Mat imgMat(img, 1);
转换函数:
//! converts header to IplImage; no data is copied
operator IplImage() const;
在将Mat转换为IplImage时,不会复制数据,即两者共享内存。
此时的转换函数实际上是Mat类中的一个转换操作符。
转换操作符是一种特殊的类成员函数。它定义将类类型值转变为其他类型值得转换。转换操作符在类定义体内声明,在保留字operator之后跟着转换的目标类型。
看看该成员函数的实现:
Mat::operator IplImage() const
{
CV_Assert( dims <= 2 );
IplImage img;
cvInitImageHeader(&img, size(), cvIplDepth(flags), channels());
cvSetData(&img, data, (int)step[0]);
return img;
}
在函数中直接定义了一个IplImage类型的变量img,然后用mat的相关参数来初始化定义的img,并通过cvSetData()将Mat的data(即数据指针)赋给img的imageData。在此也可以看出转换的前后两者间时共享数据的。
函数调用方式:
// 此处说明如何转换,不检测图像是否加载成功。并通过显示图像来展示如何操作转换得到的IplImage。
Mat img = imread("Lena.jpg");
imshow("img", img);
IplImage iplImage1(img);
cvShowImage("iplImage1", &iplImage1);
IplImage* iplImage2 = &IplImage(img);
cvShowImage("iplImage2", iplImage2);
以上主要描述了IplImage与Mat之间的转换、转换的函数实现以及转换后对图像的操作。
通过与上面类似的方式,还有CvMat与Mat的转换,两个转换函数如下:
CvMat -- > Mat
//! converts old-style CvMat to the new matrix; the data is not copied by default
Mat(const CvMat* m, bool copyData=false);
//! converts header to CvMat; no data is copied
operator CvMat() const;