1

I have been trying do a comparison of data contents in my IplImage object.

I have the following:

   IplImage img1 = IplImage(cv::imread("C:\\TestIm\\barrier_snapshot1.png"),            
                                                   CV_LOAD_IMAGE_GRAYSCALE);
   for (int i=0; i < img1.widthStep * img1.height; i++) {
       cout << img1.imageData[i] << endl;
   }

But when I try to print it, it is causing an exception and I cannot even catch it to print the message and see what I am doing wrong. My image is Grayscale and I believe if I don't use cvCreateImage() it is okay? I know it will be something stupid or related to array access that I cannot seem to be getting easily from the IplImage documenation.

*WHY AM I BOTHERING TO MIX C AND C++ CODE IN MY DESIGN? *

Unfortunately, I have no choice! I am working on a project that is with improved Motion Detection Applications. My legacy application source code uses heavy BOOST and OpenCV stuff. Especially, it uses IplImage* (I hate it, makes life difficult and causes memory leak) to store stuff like image masks. I understand that If I save IplImage* in long run I will have illegal reference and access violation. so I save the copy of the actual content pointed by the IplImage*. To exemplify:

// getLongHistory() returns IplImage*
IplImage history_long = *(motionHistory.getLongHistory()); 

There are total 6 mask images that are made using IplImage*. At this moment, I am condemning the programmer who decided to do it in IplImage*. The problem arises when I am trying to load those mask images and this is how I do it:

// Passing pointer to the address of the mask stored (alive in the memory)
motionHistory.setLongHistory(&(matcher.getCurrentSceneObject().getLongHistory()));

I believe I am having a problem with deep copy and shallow copy of IplImage objects. I believe doing saving it as cv::Mat from IplImage* and loading it as IplImage* from cv::Mat will probably reduce the burden as I suspect it probably does SOMETHING underneath the high-level functions so that the copying for data and ROI is done accordingly. But, as a newbee I can assume anything. Please help!

UPDATE

In my code I was doing this in the past:

/* I store all my mask images in a vector of pairs made of <int, IplImage>
 * __MASK_LONG__ etc. are predefined intergers
 * getMaskLong() etc. methods return IplImage* to the respective mask images.
 */

  myImages.clear(); // To make sure that I have no extra stuff
  myImages.push_back(std::make_pair<int, IplImage>(_MASK_LONG_, maskHistory.getMaskLong()));
  myImages.push_back(std::make_pair<int, IplImage>(_MASK_SHORT_, maskHistory.getMaskShort()));

However, after getting suggestions and doing some basic R&A, I am now doing this to prevent shallow copying:

  myImages.clear(); 
  myImages.push_back(std::make_pair<int, IplImage>(_MASK_LONG_, *cvCloneImage(maskHistory.getMaskLong())));
  myImages.push_back(std::make_pair<int, IplImage>(_MASK_SHORT_, *cvCloneImage(maskHistory.getMaskShort())));

I can confirm that this works as I can see the latest mask images getting loaded on the OpenCV window! And I am pretty certain how IMPORTANT it is to do Deep Copy at least 2/3 times in any programming task. So thanks for putting me to the right track. But now I have the problem which I was having in mind whilst implementing those changes - memory allocation failure. And the message was encountered:

OpenCV Error: Insufficient memory (Failed to allocate 3686404 bytes) in OutOfMemoryError, 
file /home/naresh/OpenCV-2.4.0/modules/core/src/alloc.cpp, line 52

If I am deep enough to know about C/C++, firstly I am commiting a crime of mixing them together (I HAVE NO CHOICE!! IT IS A LEGACY APPLICATION!). Secondly, there is a mismatch i.e. incorrect set of calls to malloc/free in alloc.cpp file (where the problem is being produced). Or it may just be that the heap is corrupted or full. Am I being stupid?

karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • 1
    Do you have any reason to not use the C++ API instead of the C api? Using a cv::Mat instead of an IplImage makes your life extremely easier. – Ian Medeiros Jan 31 '13 at 16:23
  • @IanMedeiros I KNEW someone would scold me for it!!! Unfortunately, yes I do! Please check my updated problem description!!! – HubbyHaguBear Jan 31 '13 at 21:15
  • Seriously, I can completely understand the eager to avoid deep copies of matrices, but working with methods returning pointers to IplImages is SCREAMING for access violations and memory leaks. The way that cv::Mat copy constructor, assignment operator and destructor are implemented already avoid deep copies of data. If there's any plan to work on this code for a long time, I would seriously think to do some refactoring. – Ian Medeiros Feb 01 '13 at 16:25
  • Another thing that bugs me out is the fact that you are being able to construct a IplImage receiving a cv::Mat as parameter. – Ian Medeiros Feb 01 '13 at 16:53
  • @IanMedeiros Bugs me out too Ian! But it works anyway! I am having more problems now. See the update! – HubbyHaguBear Feb 01 '13 at 18:03

1 Answers1

2

Don't mix the C interface of OpenCV with the C++ interface.

Ideally, you would solve the problem by using exclusively the C++ interface, like the following:

cv::Mat gray = cv::imread("C:\\TestIm\\barrier_snapshot1.png", CV_LOAD_IMAGE_GRAYSCALE);

cv::Mat_<uchar>::iterator it = gray.begin<uchar>();
cv::Mat_<uchar>::iterator end = gray.end<uchar>();
for (; it != end; ++it)
{
    cout << *it << endl;        
}

Or:

cv::Mat gray = cv::imread("C:\\TestIm\\barrier_snapshot1.png", CV_LOAD_IMAGE_GRAYSCALE);

for (int i = 0; i < gray.cols; i++)
{
    for (int j = 0; j < gray.rows; j++)
    {
        cout << gray[gray.cols * j + i] << endl;
    }
}

Yes, cv::imread() can also load an input image as grayscale. But if you really need to stick with the C interface, then drop cv::imread() and use cvLoadImage() instead. There are several posts explaining how to do this, use the search box.

If you decide to continue to mix the interfaces (please don't), check this thread since it explains how to convert IplImage* to cv::Mat.

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
  • thanks for this...I kind of figured it out knowing that my problem is probably a very old but one of the most feared problems in C/C++; Deep and Shallow Copy. The issue is that I have a very big Image Processing (Motion Detection) application that uses Boost and OpenCV libraries. The legacy code that is written to process Motion Detection Algorithm uses IplImage* heavily. Please check my problem description as I have updated it a bit to let users know where I am having the problems...I really appreciate your help and I voted you up :) – HubbyHaguBear Jan 31 '13 at 20:54