Mat -> IplImage * conversion with data copy

Edi picture Edi · May 27, 2011 · Viewed 7.2k times · Source

I have following function. I want to copy back some data from Mat to IplImage * type and return it to the main control. This is silly, but I couldn't find a proper way to do this! The cheat sheet havent say anything about Mat->IplImage * conversion WITH data copy (since I need it outside the function).

Any idea or pointer is appreciated. Best --Ali

int test(IplImage **srcImage, int num_images)
{
  vector<Mat> images(num_images); 
  for (int i = 0; i < num_images; ++i) 
  { 
    images[i] = Mat(srcImage[i]); // I guess should be correct! 
      .... 
     // some manipulations on images[i] 
  } 

  // this should be wrong!
  for (int i = 0; i < num_images; ++i) 
  { 
     cvReleaseImage(&srcImage[i]); 
     srcImage[i] = new IplImage(images[i]); 
     images[i].clear();
   } 
  return 0;
 }

Answer

etarion picture etarion · May 27, 2011

Short version: Convert to a temporary IplImage, then use cvCopy.

However, there are several issues with your code:

int test(IplImage **srcImage, int num_images)
{
  vector<Mat> images(num_images); 
  for (int i = 0; i < num_images; ++i) 
  { 
    images[i] = Mat(srcImage[i]); // I guess should be correct!

so far, yes.

      .... 
     // some manipulations on images[i] 

If the manipulations are in-place (don't reallocate the Mats), you don't need to copy the data back, since the Mat constructor didn't copy the data in the first place. If you do reallocate, then ...

  } 

  // this should be wrong!
  for (int i = 0; i < num_images; ++i) 
  { 
     cvReleaseImage(&srcImage[i]);

This can be problematic. images[i] might still be using the same memory.

     srcImage[i] = new IplImage(images[i]);

new IplImage isn't going to do you any good. It doesn't have meaningful constructors, use cvCreateImage.

     images[i].clear();

This is not neccessary, as the vector goes out of scope anyway.

   } 
  return 0;
 }

The last loop should look something like this:

for (int i = 0; i < num_images; ++i) { 
     IplImage* old = srcImage[i]; // store pointer for later deallocation in case of shared data
     IplImage src = images[i];
     srcImage[i] = cvCreateImage(...); // fill appropriate parameters here. If you didn't change size/type/etc, you might not need to create/deallocate(*)
     cvCopy(&src, srcImage[i]);
     cvReleaseImage(&old); // now it is safe to deallocate(*)
}