将cv::Mat转换为IplImage*

55

这方面的文档似乎非常零散。

我基本上有一个空的IplImage*数组(IplImage** imageArray),我正在调用一个函数来导入一个cv::Mat数组——我想将我的cv::Mat转换成一个IplImage*,以便我可以将其复制到这个数组中。

目前我正在尝试这样做:

while(loop over cv::Mat array)
{
    IplImage* xyz = &(IplImage(array[i]));
    cvCopy(iplimagearray[i], xyz);
}

这会导致段错误。

同时尝试:

while(loop over cv::Mat array)
{
    IplImage* xyz;
    xyz = &array[i];
    cvCopy(iplimagearray[i], xyz);
}

我得到了一个编译时错误:

error: cannot convert ‘cv::Mat*’ to ‘IplImage*’ in assignment

我陷入困境,不知道该如何继续下去,希望能得到一些建议 :)


可能是OpenCV C++和cvSmooth的重复问题。 - karlphillip
更新:从OpenCV 4开始,IplImage和现在称之为“传统C API”的所有内容将逐步被删除。在OpenCV 4.0“alpha”中,IplImage已经被删除,CvMat也是如此。 - godot
8个回答

22

cv::Mat 是OpenCV2.X中引入的新类型,而 IplImage* 则是“传统”的图像结构。

虽然 cv::Mat 支持在构造函数参数中使用 IplImage,但默认库不提供反向转换的功能。您需要手动提取图像头信息。(请记住,在您的示例中缺少分配 IplImage 结构的操作)。


41
它确实提供了将数据转换为IplImage的功能,创建一个带有头部信息但不复制数据的图像。所以 IplImage* img = new IplImage(mat); 是可行的。 - etarion
40
实际上,你可以这样做:IplImage iplimg = mat;,在需要 IplImage 的任何地方只需使用 &iplimg。不需要动态分配内存。 - Adi Shavit
@etarion,IplImage没有任何可以执行该转换的函数。为什么IplImage * img = new IplImage(mat)能够工作? - ajaxhe
@ajaxhe cv::Mat有一个转换运算符可以将其转换为IplImage。 - etarion
7
这个答案是错误的。请参考其他答案,它可以很容易地进行转换,应该从被接受的回答中删除,因为它可能会让其他用户感到困惑。 - Ariel M.
显示剩余5条评论

20
Mat image1;
IplImage* image2=cvCloneImage(&(IplImage)image1);

猜想这会完成工作。

编辑:如果遇到编译错误,请尝试以下方法:

cv::Mat image1;
IplImage* image2;
image2 = cvCreateImage(cvSize(image1.cols,image1.rows),8,3);
IplImage ipltemp=image1;
cvCopy(&ipltemp,image2);

你能解释一下这段代码吗? - chepseskaf
1
@chepseskaf 强制类型转换的语法显式转换。 - LovaBill
@William:在使用上述代码时,我收到了“取临时地址”的警告。 - Deepak
那是一个次优的解决方案,因为你需要手动复制像素。 - Ariel M.
你是否成功只使用头文件进行转换?另外,IplImage已经过时。如果你需要高效的代码,请使用cv::Mat代替。 - LovaBill
(IplImage)image1不起作用。 - undefined

14
 (you have cv::Mat old)
 IplImage copy = old;
 IplImage* new_image = ©

你使用新的IplImage*声明来工作。

这是最好的方法,它像魔法一样有效!所有其他方法都太复杂了,这是最好的一个。对我起了作用。 - Hassen Ch.
第一行出现了编译器错误:"不存在适合的用户定义转换从“cv :: Mat”到“IplImage”。" - Andyrey
请注意,如果不小心操作,这可能会创建 use after free 的情况。 - Luiz Felipe
这个不再起作用了。错误信息:“从cv:Mat到IplImage不存在合适的转换。” - undefined

11

这是针对dlib用户的最近修复 链接

cv::Mat img = ...
IplImage iplImage = cvIplImage(img);

2
这是唯一的解决方案,不会产生编译器错误。我将其插入了我的项目中,使用了opencv420+dlib-19.8。 - Andyrey
这应该是被接受的答案。 - undefined

1

个人认为这不是类型转换引起的问题,而是缓冲区溢出问题;是这一行代码导致的

cvCopy(iplimagearray[i], xyz);   

我认为这会导致段错误,建议您确认数组iplimagearray [i]具有足够的缓冲区大小来接收复制的数据


0
可能会出现一个问题:当使用外部 ipl 并在项目中定义了 HAVE_IPL 时,构造函数可能会出现问题。
_IplImage::_IplImage(const cv::Mat& m)
{
    CV_Assert( m.dims <= 2 );
    cvInitImageHeader(this, m.size(), cvIplDepth(m.flags), m.channels());
    cvSetData(this, m.data, (int)m.step[0]);
}

在 ../OpenCV/modules/core/src/matrix.cpp 中发现未使用/实例化,导致转换失败。

您可以按照以下方式重新实现它:

IplImage& FromMat(IplImage& img, const cv::Mat& m)
{
    CV_Assert(m.dims <= 2);
    cvInitImageHeader(&img, m.size(), cvIplDepth(m.flags), m.channels());
    cvSetData(&img, m.data, (int)m.step[0]);
    return img;
}

IplImage img;
FromMat(img,myMat);

0
根据OpenCV cheat-sheet,可以按照以下方式完成:
IplImage* oldC0 = cvCreateImage(cvSize(320,240),16,1);
Mat newC = cvarrToMat(oldC0);

cv::cvarrToMat 函数会处理转换问题。


我认为cvarrToMat在opencv 2.4.5中已经不存在了。 - Ohad Kravchick

0

如果是灰度图像,我使用这个函数并且它工作得很好!但是你必须注意函数的特性;)

CvMat * src=  cvCreateMat(300,300,CV_32FC1);      
IplImage *dist= cvCreateImage(cvGetSize(dist),IPL_DEPTH_32F,3);

cvConvertScale(src, dist, 1, 0);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接