简介
OpenCV 的 Mat
类可以表示一个N维的数组, 数组的每个位置可以是单通道或多通道. 可以用来存储图片 (灰度或彩色) 、向量、直方图等很多东西.
我们把一个存储在 Mat
中的数组记作 M
, 其中的数据分布由 M.step[]
定义. M.step[n]
可以理解为数组 M
第 n
维数据在内存中的步长 (step 或 stride), 比如二维数组的一个位于 (i,j)
处的数据的地址可以用下面的式子表示:
a d d r ( M i , j ) = M . d a t a + M . s t e p [ 0 ] ∗ i + M . s t e p [ 1 ] ∗ j \tt{addr(M_{i,j})=M.data+M.step[0]*i+M.step[1]*j} addr(Mi,j)=M.data+M.step[0]∗i+M.step[1]∗j
由此可见, 二维数组是逐行存储的, 而三维数组是逐面 (plane) 存储 (一个二维数组挨着一个, 一个二维数组可以理解成一个面) .
创建 Mat 对象
1. 创建空白 Mat 对象
创建二维数组
要创建一个 Mat
对象, 最常见的 便是使用 create(nrows, ncols, type)
方法或者与之相似的构造函数 Mat(nrows, ncols, type[, fillValue])
.
顾名思义, nrows
表示二维数组的行数, ncols
表示二维的列数, type
表示数据类型, fillValue
表示用来填充数组的值.
简单地说, 就是 "数组大小 + 数据类型 + 填充值 (可选) " .
-
数组大小除了用两个
int
值 (先行后列) 表示;也可以用cv::Size
表示, 但要注意Size
的构造函数是先列后行; -
数据类型
type
的取值可以是像CV_8UC1
、CV_32FC2
这样的值, 其中U
前的数字表示数据的位数, 比如8U
表示 8 位无符号整型数 (unsigned char
) ,32F
表示 32 位浮点数 (float
) ;C
以及其后的数字表示通道 (Channel) 数, 比如C3
就表示有 3 个通道. -
填充值用
cv::Scalar
类型表示, 只写一个数会被自动类型转换;预填充值会调用赋值运算符对Scalar
类型的重载:Mat::operator=(const Scalar& value)
代码示例:
using cv::Point, cv::Rect, cv::Size, cv::Scalar; // C++17
cv::Mat M(cv::Size(100,100), CV_8UC1, 255);
M.create(500,500,CV_32FC1);
M = 0.5;
cv::Mat white = cv::Mat(Size(100,100), CV_8UC3, Scalar(255,255,255));
cv::Mat black = cv::Mat(Size(100,100), CV_8UC3);
black = Scalar(0,0,0);
注意, create
成员方法只有当大小或者类型与当前数组不同时, 才会分配新的空间.
type
值实际上也是 int
类型;也有其他表示 type
的方法, 比如利用 cv::traits::Type<>
, 由于不常用到, 时不展开介绍 (补充链接: