《计算机视觉算法:基于OpenCV的计算机应用开发》 —2.5 理解Mat类

举报
华章计算机 发表于 2020/02/15 13:33:47 2020/02/15
【摘要】 本节书摘来自华章计算机《计算机视觉算法:基于OpenCV的计算机应用开发》 一书中第2章,第2.5.1节,作者是[伊朗] 阿明·艾哈迈迪·塔兹赫孔迪(Amin Ahmadi Tazehkandi) ,陈靖 杨欣 译。

2.5 理解Mat类

参考上一章对计算机视觉中图像的描述,任何一个图像实际上都是一个给定宽度、长度、颜色通道数量和深度的矩阵。基于此描述,我们可以说OpenCV Mat类能用来处理图像数据,而且它支持图像所需的所有属性,比如宽度和高度。事实上,Mat类是一个n维数组,用来存储任意给定数据类型的单通道或多通道数据,并且它包含了大量成员和方法,以多种方式创建、修改或操作这些数据。

本节我们将通过实际范例和代码示例来学习Mat类中一些最重要的成员和方法。

OpenCV C++ Mat类在Python版本中的等价类并不是原生的OpenCV类,而是被表示为 numpy.ndarray的数据类型。NumPy是一个Python库,包括了大量数值算法和数学运算方法,并且支持大型的多维数组和矩阵。在Python版本中使用numpy.ndarray数据类型的原因,是它提供了C++版本OpenCV Mat类所需成员和方法的最佳替代品(如果不完全相同的话)。完整的numpy.ndarray所支持的成员和方法列表请参考NumPy说明文档。

2.5.1 创建一个Mat对象

基于不同的初始化要求,Mat类包含大约20种不同的构造函数来创建类实例。让我们通过示例来看看最常用的构造函数。

创建一个Mat对象(或者类的实例),宽度1920,高度1080,包含32位浮点数表示的3个颜色通道,如下所示:

 image.png

注意,Mat构造函数中的type参数可被看成一种特殊类型的参数,也就是一个包含深度、数据类型和颜色通道数的常量。格式如下:

 image.png

<depth>可以用8、16、32或64来替换,它表示用于存储像素中每个元素的二进制数据位数。每个像素所占用的实际位数可以通过计算这个数值和颜色通道数(就是<channels>)的乘积来得到。最后,<type>可以用U、S或F来替换,U表示无符号整数,S表示有符号整数,F表示浮点数。例如,可用以下代码,分别创建宽800且高600的标准灰度图像和彩***像。注意,二者唯一的不同之处是颜色通道数,深度和数据类型参数都用8位无符号整数表示:

 image.png

你可以用以下构造函数来创建一个宽度为W、高度为H的8位无符号3通道RGB图像,然后用R、G和B的颜色值初始化所有元素:

 image.png

注意,OpenCV中颜色的默认存储顺序是BGR(而不是RGB),这意味着B和R交换了位置。如果我们的目标是在程序运行时的某个时间点显示处理过的图像,这一点尤其重要。

因此,前面的代码中正确的scalar初始化方法应该如下:

 image.png

如果我们需要创建一个高维Mat对象,可以按如下方法。注意,在下面的例子中一个7维的Mat对象被创建。sizes数组提供了每一维的大小,高维Mat中的每一个元素被称为hdm,它包含32位浮点数的双通道:

 image.png

用C++向量也可以实现相同的功能,方法如下:

 image.png

类似地,我们可以使用另外的Scalar参数来初始化Mat对象中所有的数值。注意,Scalar中的数值个数必须与通道数一致。例如,初始化上述的7维Mat对象中的所有元素,我们需要用到下面的构造函数:

 image.png

Mat类允许我们使用已经存在的图像数据进行初始化。使用这个构造函数,你可以使Mat类中的data指针所指向的数据相同。注意,这个构造函数并不是创建了一个初始化数据的完整拷贝,而是使创建的Mat对象的指针指向了它的地址。这就能非常高效地初始化和构造Mat类,但是有一个特别明显的缺点是在不再需要该类时要注意内存清理,所以在使用这个构造函数时要格外小心:

 image.png

注意,与前面的构造函数及其初始化不同,这里的data类型不是Scalar,而是指向一块内存的指针,所指向的内存含有一个1920×1080像素的三通道图像数据。这种用指针指向内存空间的初始化Mat对象方法同样适用于高维的Mat类。

最后一种构造函数类型,同时也是Mat类中最重要的构造函数之一,被称为感兴趣区域(Region Of Interest,ROI)构造函数。此构造函数用另一个Mat对象中的一个区域来初始化Mat对象。让我们用一个例子来说明。假设你有一个图像,你想对图像中的特定区域,或者说ROI,进行修改。你可以使用下面的构造函数来创建一个可访问ROI的Mat类,而且对该区域的任何更改都会影响到原始图像的相同区域。我们用下面的代码来实现:

 image.png

当image(它本身是Mat对象)包含下面左边的图片时,如果用上面的构造函数,那么roi将能访问图像中框出的区域,并包含显示在右边的图像:

 image.png

Rect类在OpenCV中用来表示一个给定了左上角点以及宽度和高度的矩形,例如,在上面的例子中Rect类的左上角点的位置为240和140,宽度为300,高度为300,如下所示:

 image.png

如前所述,对ROI的任何改动都会造成原始图像的更改。例如,我们可以将以下图像处理算法应用到roi(现在先不深究该算法,我们将会在后续章节中学习它,只需关注ROI的概念):

 image.png

如果我们尝试显示这个图像,结果应该接近下图。注意在此图中,上面图像中标注的区域被改变了(膨胀了),尽管我们改变的只是roi,而不是原图本身:

 image.png

类似于在一个图像的矩形区域使用Rect类来构造一个ROI Mat类对象一样,你同样也可以在原始的Mat对象中创建一个对应一个行和列区间的ROI。例如,上述例子的相同区域也可以被以下的构造函数访问:

 image.png

Range类在OpenCV中用来表示start和end的区间。根据start和end的数值,可以检查Range类是否为空。在上面的构造函数中,第一个Range类表示原始图像的从140行到440行的区间。第二个Range表示原始图像的从240列到540列的区间。两个区间所重叠的区域就是上面的ROI。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。