1.0 显示图片和2.0显示图片的比较
在[【循序渐进地学好OpenCV&2】显示图片——OpenCV的“起手式”](http://blog.csdn.net/zgljl2012/article/details/48306299)这篇文章里,我们使用了OpenCV 1.0的API实现了从磁盘读取文件并显示,下面是代码:
#incldue "cv.h"
#include "highgui.h"
int main(int argc, char** argv)
{
IplImage* img = cvLoadImage(argv[1]);
cvNamedWindow("Example1", CV_WINDOW_AUTOSIZE);
cvShowImage("Example1", img);
cvWaitKey(0);
cvReleaseImage(&img);
cvDestroyWindow("Example1");
}
从上面我们可以看出这是明显的C风格的代码,首先是让指针指向一块分配好的内存数据,然后释放内存,如里面的cvReleaseImage。
但在2.0的API里,我们就可以不用这么写了,因为Open CV2.0版本已经可以实现自动化的内存管理了。
下面我们使用2.0的API实现一下显示图片:
#include "highgui.h"
#include "cv.h"
using namespace cv;
int main() {
char* name = "fruits.jpg";
char* window = "显示图片";
// 将图片读入一个Mat
Mat mat = imread(name);
// 创建一个窗口
namedWindow(window);
// 显示图片
imshow(window, mat);
// 等待一个点击键盘事件
waitKey(0);
return 0;
}
效果图就不贴了,当然成功了。代码的逻辑和1.0差不多,只是少了释放内存的代码,因为2.0 的OpenCV已经实现自动化内存管理里
OpenCV 2.0的自动化内存管理
OpenCV对所有的内存实施自动化管理。首先,std::vector,Mat和其他的数据结构有它们自己的析构函数在需要的时候来负责释放底层的内存缓冲区。这意味着析构函数不是总是释放缓存。
以Mat为例,它是一个类,里面包含两个数据部分,矩阵头和一个指向存储所有像素值的矩阵的指针。矩阵头的大小是常数值,而矩阵的大小就与图像的大小有关,一般都会比矩阵头大上几个数量级。在OpenCV中,要进行大量的图像处理,因此也常常要在函数中传递Mat,这个时候,如果每次传递都将图像矩阵占据的内存一块拷贝一份的话,就会减慢处理速度;所以,除非有特殊要求,否则不应该传递图像数据。
所以,在我们拷贝Mat时OpenCV不会在给图像矩阵分配新内存了,而是给Mat创建了一个指向它的指针。并引用了计数机制,每添加一个Mat指向同一块图像矩阵的引用,计数加1;释放后计数减1。当计数为0时,表明没有指向它的指针,就释放这块内存。所以,OpenCV2.0能自动管理内存。
下面看例子:
void mat() {
// 创建一个8M的大矩阵
Mat A(1000, 1000, CV_64F);
// 创建另一个相同的矩阵头
// 这是一个瞬时的操作, 因为忽略了矩阵的大小.
Mat B = A;
// 创建一个矩阵头,只包含了A的第三行; 同样没有数据被拷贝
Mat C = B.row(3);
// clone可以拷贝矩阵本身,下面是创建了一个矩阵副本
Mat D = B.clone();
// copyTo也可以拷贝矩阵本身,但因为A、B、C指向的都是同一块矩阵数据
// 所以这是将原矩阵数据的第5行拷贝到了第3行
B.row(5).copyTo(C);
// 现在让A和D共享数据; 但原A的矩阵还被B和C引用着
A = D;
// 清空B (即让它不引用内存),
// 原A矩阵现在就只剩下C还引用着,尽管C只是一行数据
B.release();
// 最后,复制一块C指向的内存,让C指向它的新内存;这样,原A矩阵数据就被释放掉了,
// 因为这个时候,它没有被任何变量引用
C = C.clone();
}
Ptr介绍
上面的Mat是OpenCV实现了自动化内存管理,所以用起来很方便。但是对那些高等级的类和用户定义的类要实现自动化内存管理该怎么办呢?OpenCV也为这些类提供了与C++STL标准库相似的Ptr<>模板类。只需要用它来代替原来的指针即可:
T* ptr = new T(...);
//替换为:
Ptr<T> ptr = new T(...);
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-05 17:20:52