【OpenCV C++20 学习笔记】基本图像容器——Mat

概述

电子设备中储存的图像本质是图像在每个像素点上的数值,这些数据形成一个矩阵,除此之外还包括一些描述这个数值矩阵的信息。OpenCV作为一个计算机视觉库,同样也是要处理这样的信息。所以,要学习OpenCV,首要的事情是了解在OpenCV中是如何储存图像的数值矩阵以及描述信息的。
(本文较长,详细介绍了Mat对象的原理、创建方式和输出方式,读者可根据目录跳转至相关章节)

Mat

2001年OpenCV诞生的时候,是在C语言的接口上创建的,并将图像储存在一个称作IplImage的C语言数据结构中。这种方式最大的一个缺点就是需要用户自己管理内存。如果是小型的项目尚可,如果数据量变大,管理内存就会使人很头疼。
OpenCV2.0 引入了C++接口,实现了内存的自动管理。Mat成为了OpenCV储存图片信息的数据结构。
Mat不需要手动分配或释放内存,大部分的OpenCV方法都会自动为输出的Mat对象分配内存。如果你已经为一个Mat对象分配了它需要的内存,那么你在传输它的时候,这个内存会被重复利用。也就是说,在执行任务的时候,不会使用多余的内存。

内部结构

Mat实质上是一个包含了两个部分的类:

  • 矩阵头(matrix header):它包含了矩阵的大小、存储方式、存储地址等信息
  • 指向矩阵的指针:Mat对象只是储存了矩阵的指针,并没有储存矩阵本身,而矩阵中包含了像素值(像素值矩阵的维度由存储方式决定)
    Mat对象的大小是固定的,但是矩阵本身的大小是跟随图像变化的。
    在函数间传递图像是OpenCV中非常常见的操作,而且某些图像处理算法很复杂。为了提高程序的运行速度,OpenCV使用了“引用计数机制”。每个Mat对象都有自己独立的矩阵头,但是同一个矩阵可能会被多个Mat对象共享,即多个Mat对象的指针可能会指向内存中的同一个矩阵。而复制操作只会复制Mat对象的矩阵头以及指向矩阵的指针,并不会直接复制矩阵的数值!

下面的代码详细展示了Mat对象在实际应用中的内存分配问题:

Mat A, C;	//创建Mat对象的时候只是创建了矩阵头的部分
A = imread(argv[1], IMREAD_COLOR);	//读取图片,分配内存存储图片的数值矩阵,并将A的指针指向这个矩阵的内存地址

Mat B(A);	//调用复制构造函数创建B,但仅仅是将A中的指向图片矩阵的指针复制到B中,并没有复制图片的数值矩阵

C = A;	//赋值操作也只是将A中的指针复制到C中

上面的代码最终使A、B、C3个Mat对象中的指针都指向同一个图片的数值矩阵,虽然进行了复制和赋值操作,但内存中始终只有一个数值矩阵,如下图:
Mat对象示意图
因为3个Mat对象的指针都是指向同一个数据矩阵,所以在任何一个Mat对象中对数据矩阵进行修改都会影响到其他Mat对象。实际上,不同的Mat对象只是为处理同一个数据矩阵提供了不同的使用方法。但是这些Mat对象的矩阵头部分是不同的,你甚至可以创建一个只指向数据矩阵的其中一部分的Mat对象。例如,要想在图像中创建一个感兴趣区域(region of interest,ROI),你可以新建一个Mat对象:

Mat D(A, Rect(10, 10, 100, 100);	//使用矩形区域
Mat E = A(Range::all(), Range(1, 3));	//使用行和列

引用计数机制

如果像上面的例子一样,同一个数据矩阵属于不同的Mat对象,那到底谁来负责释放它的内存呢?答案是:最后一个使用它的Mat对象。这就是通过上面所说的“引用计数机制”来实现的。当有指向数据矩阵A的Mat对象被复制的时候,矩阵A的引用计数就会增加;当有指向矩阵A的Mat对象被销毁的时候,矩阵A的引用计数就会减少。当计数为0的时候,矩阵A就会被释放。
OpenCV还提供了深度复制数据矩阵的方法,当你不想只是复制指针,而是想复制矩阵的值的时候,可以使用cv::Mat::clone()cv::Mat::copyTo()方法。

Mat F = A.clone();	//将A指向的数据矩阵复制给F
Mat G;
A.copyTo(G);	//将A指向的数据矩阵复制到G

这样,修改F和G的时候就不会影响A指向的数据矩阵了。

总结一下:

  • OpenCV中函数导出的图像数据是自动分配内存的(除非特别指定不自动分配)
  • 使用OpenCV的C++接口的时候不用考虑内存管理的问题
  • 赋值运算符和复制构造函数只是复制Mat对象的头部信息和指针
  • 可以用cv::Mat::clone()cv::Mat::copyTo()方法实现底层的图片数据矩阵的复制

颜色数据格式

对于如何储存像素的值,通常从两个方面考虑:颜色空间和数据类型。
颜色空间是指利用基本的颜色组合成特定的颜色的方式。有多种方式可以选择:

  • RGB:这是最常用的,因为它与人眼编码颜色
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值