【OpenCV】IplImage与Mat的相互转换

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

2、Mat --> IplImage

转换函数:

//! 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);


Mat -- > CvMat

//! converts header to CvMat; no data is copied
operator CvMat() const;

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值