CvMat and Imread Vs IpImage and CvLoadImage

2019-04-06 20:31发布

问题:

Using OpenCv 2.4

I have two options to load images:

  1- CvMat and Imread

  2- IpImage and CvLoadImage    

Which one is better to use? I tried mixing the two and end up in seg fault.

回答1:

imread returns a Mat, not CvMat. They are the two different interfaces (Mat/imread for C++ and Ipl... and Cv.. for C interface).

The C++ interface is nicer, safer and easier to use. It automatically handles memory for you, and allows you to write less code for the same task. The OpenCV guys advocate for the usage of C++, unless some very specific project requirements force you to C.

Example (C++)

cv::Mat image = imread("path/to/myimage.jpg")
if(image.empty())
    return;

cv::imshow("Image", image);

cv::Mat bw = image > 128; // threshold image
cv::Mat crop = image(cv::Rect(0, 0, 100, 100)); // a 100px x 100px crop
crop= 0; // set image to 0

cv::waitKey();
// end code here

Note that if not stated otherwise, all matrix assignments reference the same data. In the example above, the crop matrix points to image, and setting it to zero will set that specific part of the image to 0.

To create a new copy of data, use Mat::copyTo, or Mat::clone();

And the C interface

IplImage* pImg = CvLoadImage("path/to/myimage.jpg");
if(pImg == NULL)
    return;

// ... big bloat to do the same operations with IplImage    

CvShowImage("Image", pImg);
cvWaitKey();
CvReleaseImage(&pImg); // Do not forget to release memory.
// end code here


回答2:

IplImage and Mat are both inter-convertible.

I would suggest you to use Mat and imread(), since it is very easy to get data from Mat.

Mat::data returns a pointer to the actual matrix data which in 1D and the values are easily accessible. http://opencv.itseez.com/modules/core/doc/old_basic_structures.html?highlight=mat#union%20data

If you want to add Machine Learning concepts in OpenCV for various tracking algorithms (eg OpenTLD), you can easily access data using Mat.data to get pointer to the actual matrix.

Many of the utilities of OpenCV (eg CalcOpticalFlowPyrLK, etc) require Mat. I would suggest you use Mat. IplImage is old thing now.



回答3:

This depends on how comfortable you are with pointers.In IplImage you can access data as

 data[i*widthstep+j*nchannels +k]

where i,j,k are some integers which is quite easy approach. In normal matrix of 3 dimension its not that easy to access data. For normal matrix data accessing is for a[i][j]

  *(*(a + i) + j) is the value of jth element of ith row in matrix a


回答4:

From OpenCV_2 cookbook:

This structure was inherited from the IPL library (that is the Intel Image Processing Library) now integrated with the IPP library (the Intel Integrated Performance Primitive library). If you use code and libraries that were created with the old C interface, you might need to manipulate those IplImage structures. Fortunately, there is a convenient way to convert an IplImage into a cv::Mat object.

IplImage* iplImage = cvLoadImage("c:\img.jpg"); cv::Mat image4(iplImage,false);

The function cvLoadImage is the C-interface function to load images. The second parameter in the constructor of the cv::Mat object indicates that the data will not be copied (set it to true if you want a new copy, while false is the default value so it could have been omitted), that is both IplImage and image4 will share the same image data. You need to be careful here to not create dangling pointers. For this reason, it is safer to encapsulate the IplImage pointer into the reference-counting pointer class provided by OpenCV 2:

cv::Ptr iplImage = cvLoadImage("c:\img.jpg");

Otherwise, if you need to deallocate the memory pointed by your IplImage structure, you need to do it explicitly: cvReleaseImage(&iplImage); Remember, you should avoid using this deprecate data structure. Instead, always use cv::Mat.