Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Opencv中数据结构Mat的相关属性

Opencv中数据结构Mat的相关属性

作者头像
剑影啸清寒
发布于 2018-01-02 03:39:11
发布于 2018-01-02 03:39:11
2.2K00
代码可运行
举报
文章被收录于专栏:琦小虾的Binary琦小虾的Binary
运行总次数:0
代码可运行

Opencv中数据结构Mat的相关属性

前言:

The class Mat represents an n-dimensional dense numerical single-channel or multi-channel array. It can be used to store real or complex-valued vectors and matrices, grayscale or color images, voxel volumes, vector fields, point clouds, tensors, histograms (though, very high-dimensional histograms may be better stored in a SparseMat ). Mat类用于表示一个多维的单通道或者多通道的稠密数组。它能够用来存储实数或附属的向量、矩阵、灰度/彩色图像、立体元素、点云、张量,以及直方图(虽然高维的直方图用SparseMat保存比较好)。

以上摘自OpenCV 2.4.9的官方文档opencv2refman.pdf。

以前虽然能够比较熟练的使用OpenCV,但是最近感觉其实笔者自己对OpenCV的最底层数据结构Mat与IplImage都不怎么熟悉…… 由于笔者比较反感总是需要管理内存的IplImage,所以对Mat数据结构做一下学习工作还是有必要的。

官方说明文档opencv2refman.pdf中,写出了Mat的定义如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class CV_EXPORTS Mat
{
public:
// ... a lot of methods ...
...
/*! includes several bit-fields:
- the magic signature
- continuity flag
- depth
- number of channels
*/
int flags;
//! the array dimensionality, >= 2
int dims;
//! the number of rows and columns or (-1, -1) when the array has more than 2 dimensions
int rows, cols;
//! pointer to the data
uchar* data;
//! pointer to the reference counter;
// when array points to user-allocated data, the pointer is NULL
int* refcount;
// other members
...
};

下面笔者将从几个方面总结Mat数据结构的主要组成。

参考网址: 《OpenCV中对Mat里面depth,dims,channels,step,data,elemSize和数据地址计算的理解 》 《OpenCV Mat的常见属性》 《OpenCV学习笔记(四十)——再谈OpenCV数据结构Mat详解》

参考文档: 《opencv2refman.pdf》

一. Mat重要数据成员简要列举

如上面的Mat定义源码,Mat类中有很多重要的数据类型成员。 下面进行简单的列举。

  • dims:两者表示矩阵M的维度,如3*4的矩阵为2维,3*4*5的矩阵为3维;
  • data:Mat对象中的指针,指向存放内存中存放矩阵数据的一块内存,即:uchar* data;
  • step:定义了矩阵布局的数组,具体见后面的图片解释;
  • rows, cols:矩阵的行数、列数;
  • depth:即图像每一个像素的位数(bits);具体在后面的地址部分解释;
  • type:表示了矩阵中元素的类型(depth)与矩阵的通道个数(channels);具体在后面解释;
  • channels:通道数量;若图像为RGB、HSV等三通道图像,则channels = 3;若图像为灰度图,则为单通道;
  • elemSize:矩阵中每一个元素的数据大小;具体在后面进行解释;

1. depth, channels, type, elemSize, elemSize1

把这四个数据成员放在一起,是因为这四个数据成员相互之间有关系。

(1) depth

数据的存储一直都是个值得关注的问题,所以数据元素存储的位数和范围就十分重要了。depth就体现了每一个像素的位数,即深度。 Mat中包含的图像深度如下所示:

  • CV_8U:8位无符号整数(0–255),对应Mat_< uchar>
  • CV_8S:8位有符号整数(-128–127),对应Mat_< char >
  • CV_16U:16位无符号整数(0–65535)
  • CV_16S:16位有符号整数(-32768–32767)
  • CV_32S:32位有符号整数(-2147483648–2147483647),对应Mat_< int >
  • CV_32F:32位浮点数(-FLT_MAX..FLT_MAX, INF, NAN),对应Mat_< float >
  • CV_64F:64位浮点数 ( -DBL_MAX..DBL_MAX, INF, NAN)

另外还需要注意:大部分OpenCV的函数支持的数据深度只有8位和32位,所以尽量使用CV_64F。

(2) channels

channels表示了矩阵拥有的通道数量,这个比较容易理解:

  • 若图像为RGB、HSV等三通道图像,则channels == 3;
  • 若图像为灰度图,则为单通道,channels == 1;

(3) type

type表示矩阵中元素的类型(depth)与矩阵的通道个数(channels),可以理解成上面的depth与channels的综合说明。type是一系列预定义的常量,命名规则如下: CV_+位数+数据类型+通道数 具体有如下值:

数据类型

1

2

3

4

CV_8U

CV_8UC1

CV_8UC2

CV_8UC3

CV_8UC4

CV_8S

CV_8SC1

CV_8SC2

CV_8SC3

CV_8SC4

CV_16U

CV_16UC1

CV_16UC2

CV_16UC3

CV_16UC4

CV_16S

CV_16SC1

CV_16SC2

CV_16SC3

CV_16SC4

CV_32S

CV_32SC1

CV_32SC2

CV_32SC3

CV_32SC4

CV_32F

CV_32FC1

CV_32FC2

CV_32FC3

CV_32FC4

CV_64F

CV_64FC1

CV_64FC2

CV_64FC3

CV_64FC4

表格中,行代表了通道数量channels,列代表了图像深度depth。 例如CV_8UC3,可以拆分为:

  • CV_:type的前缀
  • 8U:8位无符号整数(depth)
  • C3:3通道(channels)

注:type一般是在创建Mat对象时设定,若要去的Mat的元素类型,可以不使用type,使用depth。

(4) elemSize

elemSize表示了矩阵中每一个元素的数据大小,单位是字节。公式如下: elemSize = channels * depth / 8 例如type == CV_16SC3,则elemSize = 3 * 16 / 8 = 6 Bytes。

(5) elemSize1

elemSize1表示了矩阵元素的一个通道占用的数据大小,单位是字节。公式如下: elemSize = depth / 8 例如type == CV_16SC3,则elemSize1 = 16 / 8 = 2 Bytes。

二. Mat数据元素地址

使用OpenCV处理图像时,最普遍的处理方式便是遍历图像,即访问所有的图像像素点。但有的算法还需要访问目标像素的邻域,所以这时候就需要了解访问Mat数据元素地址的方式。

1. 像素地址计算公式

假设有矩阵M,则数据元素的地址计算公式如下:

如果是二维数组,则上述公式就简化成:

注:式中m = M.dims,即矩阵的维度。

2. 举例说明

(1) 二维矩阵

假设存在一个二维矩阵如下图所示:

上面是一个3 × 4的矩阵。此时我们按照数据类型为CV_8U, CV_8UC3的情况,分别对其进行讨论。

首先假设其数据类型为CV_8U,也就是单通道的uchar类型,则可以得出上面的数据成员情况分别为:

  • M.dims == 2:二维矩阵;
  • M.rows == 3:图像共三行;
  • M.cols == 4:图像共四列;
  • M.channels == 1:图像通道数为1;
  • M.elemSize() == 1:矩阵中每一个元素的数据大小为1,因为sizeof(uchar) == 1;
  • M.step = [4, 1]:由于是二维矩阵,所以step数组只有两个值;
    • step[0]代表一行数据大小,所以step[0] = 4 * 1 = 4;
    • step[1]代表一个元素的数据大小,即通道个数,所以step[1] = 1;

若假设其数据类型为CV_8UC3,也就是三通道的uchar类型,则可以得出上面的数据成员情况分别为:

  • M.dims == 2:二维矩阵;
  • M.rows == 3:图像共三行;
  • M.cols == 4:图像共四列;
  • M.channels == 3:图像通道数为3;
  • M.elemSize() == 1:矩阵中每一个元素的数据大小为1,因为sizeof(uchar) == 1;
  • M.step = [12, 3]:由于是二维矩阵,所以step数组只有两个值;
    • step[0]代表一行数据大小,所以step[0] = 4 * 3 = 12;
    • step[1]代表一个元素的数据大小,即通道个数,所以step[1] = 3;

(2) 三维矩阵

假设存在一个三维矩阵如下图所示:

上面是一个3 × 4 × 6的矩阵。假设其数据类型为CV_16SC4,此时对其进行讨论。

  • M.dims == 3:三维矩阵;
  • M.channels == 4:图像通道数为4;
  • M.elemSize() == M.elemSize1() * M.channels() == 2 * 4 = 8;
  • M.step = [192, 48, 3]:由于是三维矩阵,所以step数组有三个值;
    • M.step[2] == M.elemSize == 8;
    • M.step[1] == 6 * M.elemSize() == 48;
    • M.step[0] == 4 * 6 * M.elemSize() == 192;

3. 地址访问

关于OpenCV地址访问方法及效率的部分,请见笔者的博文《OpenCV像素点邻域遍历效率比较,以及访问像素点的几种方法 》。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
opencv学习(一):安装以及相关基础概念
国内网络原因可能会安装失败,多试几次可能就好了,比较玄学。实在仍然不行,可能需要配置下代理。
ACK
2020/01/14
6750
降龙算法1:图像的基本数据格式(8K字)
开始更新降龙算法系列了。因为停更近半年了,所以先啰嗦几句话交代一下这个系列的前因后果:
周旋
2023/01/30
5860
OpenCV两种畸变校正模型源代码分析以及CUDA实现
图像算法中会经常用到摄像机的畸变校正,有必要总结分析OpenCV中畸变校正方法,其中包括普通针孔相机模型和鱼眼相机模型fisheye两种畸变校正方法。 普通相机模型畸变校正函数针对OpenCV中的cv::initUndistortRectifyMap(),鱼眼相机模型畸变校正函数对应OpenCV中的cv::fisheye::initUndistortRectifyMap()。两种方法算出映射Mapx和Mapy后,统一用cv::Remap()函数进行插值得到校正后的图像。 1. FishEye模型的畸变校正。
一棹烟波
2018/01/12
4.4K0
OpenCV两种畸变校正模型源代码分析以及CUDA实现
OpenCV 创建图像时,CV_8UC1,CV_32FC3,CV_32S等参数的含义
形式:CV_<bit_depth>(S|U|F)C<number_of_channels>
种花家的奋斗兔
2020/11/13
3.7K0
【从零学习OpenCV 4】图像距离变换
图像中两个像素之间的距离有多种定义方式,图像处理中常用的距离有欧式距离、街区距离和棋盘距离,本节中将重点介绍这三种距离的定义方式,以及如何利用两个像素间的距离来描述一幅图像。欧式距离,两个像素点之间的直线距离。与直角坐标系中两点之间的直线距离求取方式相同,分别计算两个像素在X方向和Y方向上的距离,之后利用勾股定理得到两个像素之间的距离,数学表示形式如式(6.1)所示。
小白学视觉
2020/02/12
1.3K0
【从零学习OpenCV 4】图像距离变换
【从零学习OpenCV 4】图像卷积
过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《从零学习OpenCV 4》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。
小白学视觉
2019/12/24
7560
【从零学习OpenCV 4】图像卷积
【从零学习OpenCV 4】LUT查找表
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《从零学习OpenCV 4》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。
小白学视觉
2019/11/30
8810
【OpenCV教程】core 模块 - 常用数据结构的使用
大家都知道,利用函数imwrite,可以将一个矩阵写入图像文件中。但是为了debug,更加方便的方式是看实际值,我们可以通过 Mat的运算符 << ,来实现同样的功能,但这只对二维矩阵有效。
小白学视觉
2019/07/15
7240
【OpenCV教程】core 模块 - 常用数据结构的使用
【AI白身境】搞计算机视觉必备的OpenCV入门基础
它是一款由Intel公司俄罗斯团队发起并参与和维护的一个计算机视觉处理开源软件库。
用户1508658
2019/07/26
9950
【AI白身境】搞计算机视觉必备的OpenCV入门基础
【从零学习OpenCV 4】Mat类构造与赋值
前一小节已经介绍了三种构造Mat类变量的方法,但是后两种没有给变量初始化赋值,本小节将重点介绍如何灵活的构造并赋值Mat类变量。根据OpenCV的源码定义,关于Mat类的构造方式共有二十余种,然而在平时一些简单的应用程序中很多复杂的构造方式并没有太多的用武之地,因此本书重点讲解笔者在学习和做项目中常用的构造与赋值方式。
小白学视觉
2019/10/31
4.3K0
【从零学习OpenCV 4】Mat类构造与赋值
万字长文,值得收藏/参考的OpenCV C++基础代码
一位友好人士做的B站OpenCV4.x C++ 快速入门30讲视频课程的笔记总结!我只能点赞了!
OpenCV学堂
2021/08/06
1.2K0
OpenCV的Mat类型以及基本函数使用
在OpenCV中IplImage是表示一个图像的结构体,也是从OpenCV1.0到目前最为重要的一个结构;在之前的图像表示用IplImage,而且之前的OpenCV是用C语言编写的,提供的接口也是C语言接口。
职场亮哥
2020/10/10
1.6K0
OpenCV基础03--创建空白图像和显示
以下程序也与以前的程序非常相似。唯一的区别是该程序创建一个空白图像,而不是从文件加载现有图像。
软件架构师Michael
2023/09/11
6850
OpenCV中高效的像素遍历方法,写出工程级像素遍历代码
初次接触OpenCV的开发者,必须过的第一道坎就是学会如何遍历访问Mat对象中每个像素,实现像素级别的图像操作,这个是最级别的编程技能,但是不同的像素遍历方法效率有云泥之别,相差特别大,甚至可能成为算法运行的瓶颈之一,因此找到一种速度快的遍历方法对大图像处理是很关键的。在开始寻找高效遍历方法之前,先来了解一下Mat对象的数据组织形式与像素块数据的存储方式,Mat对象由两个部分组成,元数据头部加像素数据块部分,图示如下:
OpenCV学堂
2019/07/05
5.5K1
OpenCV加载图片显示对应类型(位深度)方法
对于部分初学者,偶尔会想在代码中查看图片的位深度,一般我们会用Mat.type()来获得类型,但是默认输出的是整型数字,不便于理解,可能还需要自己对照宏定义去查看,这里有一段代码可以实现将整型转为宏定义位深度
Color Space
2020/07/24
3.1K0
OpenCV加载图片显示对应类型(位深度)方法
OpenCV图像处理04-Mat对象
IplImage在OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,容易导致内存泄漏问题。OpenCV4.*版本已经淘汰该类型。
yangjiao
2021/03/04
5040
【从零学习OpenCV 4】这4种读取Mat类元素的的方法你都知道么?
对于Mat类矩阵的读取与更改,我们已经在矩阵的循环赋值中见过如何用at方法对矩阵的每一位进行赋值,这只是OpenCV提供的多种读取矩阵元素方式中的一种,本小节将详细介绍如何读取Mat类矩阵中的元素,并对其数值进行修改。在学习如何读取Mat类矩阵元素之前,首先需要知道Mat类变量在计算机中是如何存储的。多通道的Mat类矩阵是一个类似于三维的数据,而计算机的存储空间是一个二维空间,因此Mat类矩阵在计算机存储时是将三维数据变成二维数据,先存储第一个元素每个通道的数据,之后再存储第二个元素每个通道的数据。每一行的元素都按照这种方式进行存储,因此如果我们找到了每个元素的起始位置,便可以找到这个元素中每个通道的数据。图2-5展示了一个三通道的矩阵的存储方式,其中连续的蓝色、绿色和红色的方块分别代表每个元素的三个通道。
小白学视觉
2019/11/07
3.7K0
【从零学习OpenCV 4】这4种读取Mat类元素的的方法你都知道么?
OpenCV学习笔记:MAT解析
但手动地做还是可以的:大多数OpenCV函数仍会手动地为输出数据开辟空间。当传递一个已经存在的 Mat 对象时,开辟好的矩阵空间会被重用。也就是说,我们每次都使用大小正好的内存来完成任务。
bear_fish
2018/09/19
8610
OpenCV学习笔记:MAT解析
OpenCV图像处理笔记(一):图片基本操作
==如果有报无法找到opencv_world343.dll的Error,请把C:\opencv\build\x64\vc14\bin下的opencv_world343.dll文件复制到C:\Windows 目录下即可==
MiChong
2020/09/24
1.7K0
OpenCV图像处理笔记(一):图片基本操作
10、图像的几何变换——平移、镜像、缩放、旋转、仿射变换 OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(1)OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)数字图像
  图像几何变换又称为图像空间变换,它将一副图像中的坐标位置映射到另一幅图像中的新坐标位置。我们学习几何变换就是确定这种空间映射关系,以及映射过程中的变化参数。图像的几何变换改变了像素的空间位置,建立一种原图像像素与变换后图像像素之间的映射关系,通过这种映射关系能够实现下面两种计算:
vv彭
2020/10/27
4.2K0
10、图像的几何变换——平移、镜像、缩放、旋转、仿射变换
    


OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(1)OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)数字图像
推荐阅读
相关推荐
opencv学习(一):安装以及相关基础概念
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验