使用 OpenCv 2.4
我有两个加载图像的选项:
1- CvMat and Imread
2- IpImage and CvLoadImage
哪个更好用?我尝试将两者混合并最终出现段错误。
使用 OpenCv 2.4
我有两个加载图像的选项:
1- CvMat and Imread
2- IpImage and CvLoadImage
哪个更好用?我尝试将两者混合并最终出现段错误。
imread
返回 a Mat
,而不是CvMat
。它们是两个不同的接口(Mat
/imread
用于 C++ 和 Ipl... 和 Cv.. 用于 C 接口)。
C++ 接口更好、更安全、更易于使用。它会自动为您处理内存,并允许您为同一任务编写更少的代码。OpenCV 家伙提倡使用 C++,除非某些非常具体的项目要求迫使您使用 C。
示例 (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
请注意,如果没有另外说明,所有矩阵分配都引用相同的数据。在上面的示例中,crop
矩阵指向image
,并将其设置为零会将 的特定部分设置image
为 0。
要创建数据的新副本,请使用 Mat::copyTo 或 Mat::clone();
和C接口
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
IplImage 和 Mat 都是可相互转换的。
我建议你使用 Mat 和 imread(),因为从 Mat 中获取数据非常容易。
Mat::data 返回一个指向一维实际矩阵数据的指针,并且这些值很容易访问。http://opencv.itseez.com/modules/core/doc/old_basic_structures.html?highlight=mat#union%20data
如果您想在 OpenCV 中为各种跟踪算法(例如 OpenTLD)添加机器学习概念,您可以使用 Mat.data 轻松访问数据以获取指向实际矩阵的指针。
OpenCV 的许多实用程序(例如 CalcOpticalFlowPyrLK 等)都需要 Mat。我建议你使用Mat。IplImage 现在是老东西了。
这取决于您对指针的舒适程度。在 IplImage 中,您可以访问数据为
data[i*widthstep+j*nchannels +k]
其中 i,j,k 是一些整数,这是非常简单的方法。在 3 维的普通矩阵中,访问数据并不容易。对于普通矩阵数据访问是针对 a[i][j]
*(*(a + i) + j) is the value of jth element of ith row in matrix a
来自 OpenCV_2 食谱:
此结构继承自 IPL 库(即英特尔图像处理库),现在与 IPP 库(英特尔集成性能原语库)集成。如果您使用使用旧 C 接口创建的代码和库,则可能需要操作这些 IplImage 结构。幸运的是,有一种方便的方法可以将 IplImage 转换为 cv::Mat 对象。
IplImage* iplImage = cvLoadImage("c:\img.jpg"); cv::Mat image4(iplImage,false);
函数 cvLoadImage 是用于加载图像的 C 接口函数。cv::Mat 对象的构造函数中的第二个参数表示数据不会被复制(如果需要新的副本,请将其设置为 true,而 false 是默认值,因此可以省略),即两者IplImage 和 image4 将共享相同的图像数据。您需要注意不要创建悬空指针。为此,将 IplImage 指针封装到 OpenCV 2 提供的引用计数指针类中会更安全:
cv::Ptr iplImage = cvLoadImage("c:\img.jpg");
否则,如果需要释放 IplImage 结构指向的内存,则需要显式执行: cvReleaseImage(&iplImage); 请记住,您应该避免使用这种过时的数据结构。相反,始终使用 cv::Mat。