OpenCV中,Mat是最基础的数据处理单元,矩阵可以用Mat表示,图像可以用Mat表示,向量也可以用Mat表示,它们之间有何区别?
理解好Mat对学好OpenCV有很大帮助。相信很多人和我一样,接触OpenCV时,被Mat弄得一头雾水。我这里写一些我对Mat的理解。
1. Mat的存储结构
平时我们看见的图像,在计算机眼里其实是个大的数字矩阵。图像涉及到通道,而且像素值是正整数,而我们印象中的矩阵是没有这些特点的。OpenCV为了把图像和一般的矩阵统一到Mat中,特地给矩阵添加了一个矩阵头。
Mat本质上是有由一个矩阵头和一个指针组成的类。矩阵头包含了矩阵的大小,存储的方法,存储的地址等,指针指向了一个包含像素值的矩阵。
矩阵头的大小是恒定的,而矩阵本身的大小因图像的不同而不同,通常是较大的数量级。OpenCV 是图像处理库,一般图像的像素值矩阵非常大,矩阵头能让我们对图像进行一些操作时变得更加快捷和方便。
我们来看看Mat的存储形式。Mat和Matlab里的数组格式有点像,但一般是二维向量,如果是灰度图,一般存放<uchar>类型;如果是RGB彩色图,存放<Vec3b>类型。
单通道灰度图数据存放格式:
多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:
注意通道的顺序反转了:BGR。通常情况内存足够大的话图像的每一行是连续存放的,也就是在内存上图像的所有数据存放成一行,这中情况在访问时可以提供很大方便。可以用 isContinuous()函数来判断图像数组是否为连续的。
比如我们读入一个100×100的灰度图像img1和一个100×100的RGB彩色图像img2。然后输出各自的矩阵,会发现img1输出了一个100×100的矩阵,而img2输出了一个300×100的矩阵。因为RGB图像每个像素点上有3个值,而灰度图像只有1个,尽管图像的size是一样的。
2. 深入Mat类
Mat是矩阵,对矩阵的操作有很多的方法,这里我们只介绍Mat类里面包含的方法,其他的方法再单独介绍。
Mat类非常大,大多数是各种函数和模板,还有一些内部的定义和结构体什么的。让我们来分类了解下。
2.1 矩阵的构造、初始化、释放
2.1.1 只构造矩阵头,无数据
Mat();
//构造2维矩阵头
Mat(int rows, int cols, int type);
Mat(Size size, int type);
//构造n维矩阵头
Mat(int ndims, const int* sizes, int type);
//创建矩阵头
void create(int rows, int cols, int type);
void create(Size size, int type);
void create(int ndims, const int* sizes, int type);
//创建一个指定行数的矩阵头
Mat row(int y) const;
//创建一个指定列数的矩阵头
Mat col(int x) const;
//创建一个