问题
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.
来源:https://stackoverflow.com/questions/11115272/cvmat-and-imread-vs-ipimage-and-cvloadimage