55

The documentation on this seems incredibly spotty.

I've basically got an empty array of IplImage*s (IplImage** imageArray) and I'm calling a function to import an array of cv::Mats - I want to convert my cv::Mat into an IplImage* so I can copy it into the array.

Currently I'm trying this:

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

Which generates a segfault.

Also trying:

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

Which gives me a compile time error of: error: cannot convert ‘cv::Mat*’ to ‘IplImage*’ in assignment

Stuck as to how I can go further and would appreciate some advice :)

amr
  • 1,255
  • 3
  • 15
  • 23
  • possible duplicate of [OpenCV C++ and cvSmooth](http://stackoverflow.com/questions/5449946/opencv-c-and-cvsmooth) – karlphillip May 31 '11 at 14:07
  • Update: from OpenCV 4, IplImage and all of what they now call "the legacy C API" will be progressively removed. In OpenCV 4.0 "alpha", IplImage is already gone - as is CvMat. – godot Oct 09 '18 at 17:47

8 Answers8

22

cv::Mat is the new type introduce in OpenCV2.X while the IplImage* is the "legacy" image structure.

Although, cv::Mat does support the usage of IplImage in the constructor parameters, the default library does not provide function for the other way. You will need to extract the image header information manually. (Do remember that you need to allocate the IplImage structure, which is lack in your example).

rptwsthi
  • 10,094
  • 10
  • 68
  • 109
YeenFei
  • 3,180
  • 18
  • 26
  • 41
    It does provide a conversion to IplImage, creating a header without copying the data. So `IplImage* img = new IplImage(mat);` should work. – etarion Jan 12 '11 at 13:12
  • 40
    Actually, you can do this: `IplImage iplimg = mat;` and just use `&iplimg` wherever you need an `IplImage`. There is no need for dynamic allocation. – Adi Shavit Jun 23 '11 at 19:09
  • @etarion The IplImage doesn't have any function which can do that conversion. Why does IplImage* img = new IplImage(mat) is working? – ajaxhe Dec 10 '13 at 03:52
  • @ajaxhe cv::Mat has a conversion operator to IplImage. – etarion Dec 11 '13 at 15:02
  • @etarion Yes, I found conversion operation in cv::Mat , the function name declaration is: operator IplImage() const; – ajaxhe Dec 14 '13 at 13:59
  • 7
    This answer is false. See other answers, it can be converted very easily, should be removed from accepted answer as it might confuse other users. – Ariel M. Aug 01 '15 at 17:31
  • @etarion, I know this is late. But I'm just wondering: If we use `new IplImage(mat)`, we need to *deallocate* it later by calling `free(...)` right? If it is the case, wouldn't it be better to use @Adi Shavit 's approach? – IgNite Jan 28 '20 at 21:13
  • @AdiShavit Doing`IplImage iplimg = mat;` now doesn't work. It gives an error saying: "conversion from ‘cv::Mat’ to non-scalar type ‘IplImage {aka _IplImage}’ requested" – Lakshya Goyal Feb 12 '20 at 00:11
  • Of course it doesn't. Please read the answer. `IplImage` is a C struct and you can't assign anything else to it. This is a really old question - you should really be using OpenCV and not IPL anyway. – Adi Shavit Feb 12 '20 at 05:32
20
Mat image1;
IplImage* image2=cvCloneImage(&(IplImage)image1);

Guess this will do the job.

Edit: If you face compilation errors, try this way:

cv::Mat image1;
IplImage* image2;
image2 = cvCreateImage(cvSize(image1.cols,image1.rows),8,3);
IplImage ipltemp=image1;
cvCopy(&ipltemp,image2);
LovaBill
  • 5,107
  • 1
  • 24
  • 32
14
 (you have cv::Mat old)
 IplImage copy = old;
 IplImage* new_image = ©

you work with new as an originally declared IplImage*.

ButterDog
  • 5,115
  • 6
  • 43
  • 61
user2103629
  • 141
  • 1
  • 2
10

Here is the recent fix for dlib users link

cv::Mat img = ...
IplImage iplImage = cvIplImage(img);
minhazur
  • 4,928
  • 3
  • 25
  • 27
  • 1
    This is the only solution, which doesn't generate compiler error. I inserted it in my project with opencv420+dlib-19.8 – Andyrey Mar 03 '20 at 10:56
1

Personaly I think it's not the problem caused by type casting but a buffer overflow problem; it is this line

cvCopy(iplimagearray[i], xyz);   

that I think will cause segment fault, I suggest that you confirm the array iplimagearray[i] have enough size of buffer to receive copyed data

Sotiris
  • 38,986
  • 11
  • 53
  • 85
octavian
  • 11
  • 1
0

According to OpenCV cheat-sheet this can be done as follows:

IplImage* oldC0 = cvCreateImage(cvSize(320,240),16,1);
Mat newC = cvarrToMat(oldC0);

The cv::cvarrToMat function takes care of the conversion issues.

chayan
  • 29
  • 1
  • 6
0

In case of gray image, I am using this function and it works fine! however you must take care about the function features ;)

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

cvConvertScale(src, dist, 1, 0);
ksolid
  • 151
  • 1
  • 2
  • 5
0

One problem might be: when using external ipl and defining HAVE_IPL in your project, the ctor

_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]);
}

found in ../OpenCV/modules/core/src/matrix.cpp is not used/instanciated and conversion fails.

You may reimplement it in a way similar to :

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);
Timm
  • 51
  • 5