opencv_tutorials2.4.8翻译(一)-Mat

Mat

   一直以来Opencv库提供的都是C接口,并且使用一个叫做Iplimage的C语言结构体来对图像进行存储。之前在老的教程或者书籍都会看到它。而一个众所周知的关于C语言优缺点问题就是我们需要手动对内存进行操作。即我们需要显示的进行内存的分配和释放。这对于一个小的程序不是什么问题,然而当我们的代码库不断增加时,我们就要去费力的去解决这个问题,而没有把精力放到程序开发上了(once your code base grows it will be more of a struggle to handle all this rather than focusing on solving your developing goal

  很幸运的是,C++的到来引入了类的概念,它自动的对内存进行管理(不是全部)减轻了用户编程的负担。而C++完全兼容C使得以前的代码可以不做任何修改。因此Opencv2.0引入的C++接口提供了一种新的方法使得我们不需要思考内存的管理,并且让我们的代码变得更加整洁。一个缺点就是C++对于嵌入式设备支持不够,因此除非你你的目标机是嵌入式平台你可以使用1.0版本的C语言编写,否则强烈推荐你转到Opencv2.0上来。

  第一个需要学习的就是Mat,Mat使得你不需要再手动的分配和释放内存。绝大多数的Opencv函数自动分配输出数据的内存。一个很好的例子就是(某个函数的作用)传递一个已存在的Mat对象,这个函数将自动分配这个矩阵所需空间,而其实这个已存在的矩阵是被重用的,换句话说在一个任务(函数周期)执行过程当中,系统仅对正在执行的任务分配内存空间。

  Mat是一个最基本的类,它由两部分构成:一个是Mat头(包括矩阵大小,存储类型,以及矩阵存储地址等信息),二是矩阵指针,它指向了矩阵包含的像素值(我简称Mat体)(维度取决于Mat头中的存储类型)。Mat头的大小是一个常量,但是Mat体在图像的变换过程中会因为维度的改变或者其他因素而变化。

  OpenCV是一个图像处理库。它包含了大量图像处理函数。在我们解决一个计算难题时,大部分时间我们只需要通过函数库的调用来完成。因此,传递图像参数进函数是很普遍的。而我们也应该在使用之前充分考虑图像处理算法,因为利用Opencv函数库的计算量也是和这些算法相当的。很重要的一点是我们要考虑我们程序中因不必要的潜在大图像的拷贝而对速度产生的影响,下面我们将进行讨论。

  为了解决上面的问题,Opencv使用了一个引用计数系统(类似于操作系统中文件系统的存储引用模式)。解释起来就是,每个Mat对象都有自己的头,但是两个矩阵对象通过矩阵指针指向同一块Mat体来实现共享。举几个拷贝操作函数例子,这几个函数仅拷贝头和指向Mat体的指针,而不做数据的迁移(解决了上面的问题)。

Mat A, C;   //仅创建Mat头
A = imread(argv[1], CV_LOAD_IMAGE_COLOR); //我们会知道如何为矩阵分配内存的

Mat B(A); //使用一个拷贝构造函数

C = A;  //赋值操作

上面这段代码中所有的Mat对象的指针都指向同一块Mat体,但它们有着不同的Mat头,但是,有个问题就是通过这其中任意一个Mat对象对这块Mat体操作,会对其他所有的Mat对象产生影响,这里要清楚。实际上不同的Mat对象有着多种方法对Mat体进行访问。有一个叫做ROI(region of interest)即感兴趣区域,它可以通过创建一个Mat头来指向一个完整Mat体的一部分即ROI。例如对于一个图像创建一块ROI就相当于创建了一个新的Mat头带有新的边界:

Mat D(A, Rect(10, 10, 100, 100) ); //using a rectangle
Mat E = A(Range: all(), Range(1, 3) ); //using a row and column boundaries

  现在你也许会产生疑问一个Mat体属于多个Mat对象,那最后谁来负责释放这块不再需要的内存。最直接的答案就是:最后一个Mat对象来释放。具体来说,是通过一个引用计数机制来实现的。当一个Mat体在被拷贝到一个新的Mat对象中时,计数器会加1,而当一个指向这个Mat体的Mat结构被析构掉,计数器会做减1操作,当计数器为0时,系统将自动释放掉这块Mat体的存储空间。如果你想拷贝Mat体可以通过OpenCV提供的clone()和copyTo()来实现。

Mat F = A.clone();
Mat G;
A.copyTo(G);

  这样修改F或者G所指向的Mat体将不会影响到A所指向的Mat体。回顾一下我们需要记住的是以下几点:

  • 输出图像的内存分配是Opencv函数自动完成的
  • 你不需要考虑Opencv的C++接口是如何完成内存管理的
  • 对于不同Mat对象的赋值操作和拷贝构造函数仅拷贝Mat头
  • 如果希望拷贝Mat体需要使用clone()和copyTo()函数


     
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值