一、Mat 是什么

Mat 是 OpenCV核心图像 / 矩阵容器 ,用来在内存中存放图片、视频帧、矩阵数据,替代老旧的 IplImage,自带自动内存管理,不会轻易内存泄漏。 简单理解:图片加载到内存后,全部像素数据都存在 Mat 里,所有图像处理函数(滤波、裁剪、缩放、识别)都必须接收 Mat 作为输入输出。

Mat的输出一般包含图像的宽度、高度、通道数量、通道深度、字节类
Mat 内部两大组成部分
- 矩阵头(Header,轻量) 固定大小,存图像描述信息:
- rows:图像高度(行数,H)
- cols:图像宽度(列数,W)
- channels:通道数(灰度图 1 通道,RGB 彩色 3 通道)
- type:像素数据类型(CV_8UC3、CV_8UC1 等)
- data:指针,指向真实像素缓冲区
- refcount:引用计数器(内存自动回收核心)
- 像素数据缓冲区(Data,大块内存) 真正存每个像素数值,占用内存远大于头部,存放在堆内存。
二、Mat的深度和字节类型


上面是Opencv的字节类型和通道数的定义,在OPENCV中通常分为四个通道和8种数据类型。分别是单通道(灰度图 )、双通道(二值图像 )、三通道(RGB彩色图像 )、四通道(带 Alpha 的四通道图像)。
灰度图:

灰度图又称之为灰阶图,颜色介于白色和黑色之间按对数关系分为若干等级,这种图像称之为灰度。灰度分为256个阶
二值图像:

二值图像中的图像中每一个像素只有两个值分别是0和1,其中0表示黑色、1表示白色
三通道图像:

三通道(RGB)图像也就是我们所说的RGB图像,所以三通道图像可以用来彩色图像。
四通道图像:

四通道(ARGB)也就是在彩色图像中
1. 单通道分类:
CV_8UC1:指的是一个8位无符号整型单通道矩阵
CV_32SC1:指的是一个32位整型单通道矩阵
CV_32FC1:指的是一个32位浮点型单通道矩阵
CV_64FC1:指的是一个64位浮点型单通道矩阵
CV_16SC1:指的是一个16位整型单通道矩阵
2. 双通道分类:
CV_8UC2:指的是一个8位无符号整型双通道矩阵
CV_32SC2:指的是一个32位整型双通道矩阵
CV_32FC2:指的是一个32位浮点型双通道矩阵
CV_64FC2:指的是一个64位浮点型双通道矩阵
CV_16SC2:指的是一个16位整型双通道矩阵
3.三通道分类:
CV_8UC3:指的是一个8位无符号整型三通道矩阵
CV_32SC3:指的是一个32位整型三通道矩阵
CV_32FC3:指的是一个32位浮点型三通道矩阵
CV_64FC3:指的是一个64位浮点型三通道矩阵
CV_16SC3:指的是一个16位整型三通道矩阵
4.四通道分类:
CV_8UC4:指的是一个8位无符号整型四通道矩阵
CV_32SC4:指的是一个32位整型四通道矩阵
CV_32FC4:指的是一个32位浮点型四通道矩阵
CV_64FC4:指的是一个64位浮点型四通道矩阵
CV_16SC4:指的是一个16位整型四通道矩阵
通道(channels)是什么?
一张图片每个像素由几组数字组成,几组就是几通道。
1 通道(单通道 CV_8UC1)
灰度图:每个像素只有 1 个数值,代表亮度,范围 0~255
- 0 = 纯黑
- 255 = 纯白
- 中间数字是深浅灰色 例:黑白摄像头、灰度掩码、二值图。
3 通道(三通道 CV_8UC3)
彩色 BGR 图(OpenCV 默认顺序 B/G/R,不是 RGB) 每个像素存 3 个数字,分别代表蓝、绿、红,混合出千万种颜色。 例:日常拍照、摄像头彩色画面。
4 通道(四通道 CV_8UC4)
BGR+Alpha 透明通道,第 4 个数字控制透明度。 例:PNG 透明图片,UI 贴图。
一句话总结
通道 = 每个像素存几组颜色 / 亮度数据。
多少位代表什么
代表单个数值占用多少二进制存储空间,决定数值能取多大范围。
1. 8 位(8 bit)
1 字节存储一个数字,二进制最多 8 个 0/1,最大值:\(2^8-1 = 255\) 取值范围:0 ~ 255 日常图片、摄像头画面全是 8 位,最常用。
2. 16 位(16 bit)
2 字节存储,最大值 \(2^{16}-1=65535\) 范围更大,用来存:相机 RAW 原始帧、红外、高精度灰度,普通肉眼图片不用。
3. 32 位浮点(32F)
4 字节,小数,能存小数点,用于算法计算(梯度、卷积、数学运算),不能直接存图片。
通俗理解
位数越大,能表达的明暗 / 色彩层次越多,但占用内存翻倍。 8 位 1 张 1080P 图几 MB,16 位直接翻倍。
U / S / F:无符号、有符号、浮点 区别
1. U = unsigned 无符号整数(最常用,图片专用)
- 只能存 **≥0 的正数 **
- 8U:0 ~ 255
- 16U:0 ~ 65535 图片亮度没有负数,所有原图都用 U 类型。
2. S = signed 有符号整数
可以存负数 + 正数 8S 范围:-128 ~ 127 用途:图像处理差值、差分图(比如前后帧相减会出现负数)。
3. F = float 浮点型(小数)
带小数点,例如 0.35、12.8、-2.1
- 32F:32 位单精度浮点 用途:算法计算、归一化、梯度、深度学习矩阵,不能直接显示图片。
拆解规则:CV_位数 + U/S/F + C通道数
CV_8UC18 位、无符号、1 通道 → 8 位灰度图CV_8UC38 位、无符号、3 通道 → 普通彩色 BGR 图CV_16UC116 位、无符号、单通道 → 相机 RAW 高精度灰度CV_32FC132 位浮点、单通道 → 算法浮点计算矩阵CV_8SC18 位有符号单通道 → 带负数的差分图像
三、Mat的创建和构造方法
Mat的创建一般分为五种方式:
3.1.Mat(int rows, int cols, int type);
重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是rows、cols以及存储类型type
rows **:**行数,也指的是图像的高度,height。
cols **:**列数,也指的是图像的宽度,width。
type **:**通道类型,具体的看上面的图
示例:Mat t1 = Mat(300,300,CV_8UC1),这指的是创建一个width:300,height:300,单通道的灰度图像.
3.2.Mat(Size size, int type);
重载的构造函数,这个构造函数在创建的时候,需要传入Size类和类型。
第一个传参:Size结构体,Size(width,height)
第二个传参:type通道类型,具体的看上面的图
示例:Mat t2 = Mat(Size(300,300),CV_8SC3),这指的是创建一个width:300,height:300,三通道的灰度图像
3.3.Mat(int rows, int cols, int type, const Scalar& s);
重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是rows、cols、存储类型type、还有Scalar颜色标量。
第一个传参: rows行数,也指的是图像的高度,height。
第二个传参: cols列数,也指的是图像的宽度,width。
第三个传参: type通道类型,具体的看上面的图
**第四个传参:**Scalar颜色标量,Scalar(v0,v1,v2,v3),v0,v1,v2,v3分别对应OPENCV颜色分量的四个值
示例: Mat mat = Mat(300,300,CV_8UC3,Scalar(255,255,255));表示的是创建一个cols:300,rows:300,三通道的灰度,颜色标量为白色的图像
3.4.Mat::zeros(rows,cols,type);
重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是rows、cols以及存储类型type。ZROS相当于创建一张黑色的图片,每个像素通道为0,并且Scalar(0,0,0)。
第一个传参: rows行数,也指的是图像的高度,height。
第二个传参: cols列数,也指的是图像的宽度,width。
第三个传参: type通道类型,具体的看上面的图
示例: Mat::zeros(300,300,CV_8SC3);,这指的是创建一个width:300,height:300,三通道的彩色图像,Scalar(0,0,0),相当于
Mat mat = Mat(300,300,CV_8SC3,Scalar(0,0,0));
3.5.Mat::ones(rows,cols,type);
重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是rows、cols以及存储类型type。ONES相当于每个像素第一个通道为1,后面两个通道为0。
第一个传参: rows行数,也指的是图像的高度,height。
第二个传参: cols列数,也指的是图像的宽度,width。
第三个传参: type通道类型,具体的看上面的图
示例: Mat::ones(300,300,CV_8SC3),这指的是创建一个width:300,height:300, 三通道的彩色图像,Scalar(1,0,0),
这等同于Mat mat = Mat(300,300,CV_8SC3,Scalar(1,0,0));
四、代码实现OPENCV创建Mat
完整代码
// 引入OpenCV总头文件,包含核心数据结构、基础算法等绝大多数常用功能
#include <opencv2/opencv.hpp>
// 引入深度神经网络推理模块头文件,用于加载AI模型、执行前向推理
#include <opencv2/dnn.hpp>
// 引入图像编解码模块头文件,提供imread/imwrite等图片读写功能
#include <opencv2/imgcodecs.hpp>
// 引入图像处理模块头文件,提供滤波、几何变换、绘制等图像处理算法
#include <opencv2/imgproc.hpp>
// 引入C++标准输入输出库头文件,用于控制台打印、输入输出交互
#include <iostream>
// 声明使用cv命名空间,后续代码可直接写Mat、imwrite,无需加cv::前缀
using namespace cv; //Must Need Write cv
// 声明使用std标准命名空间,后续代码可直接写cout、string等,无需加std::前缀
using namespace std;
// 程序主入口函数
int main()
{
// 创建300行×300列的3通道8位无符号彩色图像,并用指定BGR颜色整体填充
// 参数说明:Mat(行数, 列数, 像素格式, 初始填充值)
// CV_8UC3:8位无符号整数、3通道彩色图像(BGR顺序)
// Scalar(蓝, 绿, 红):OpenCV默认通道顺序为BGR,此处填充粉紫色
Mat t0 = Mat(300,300,CV_8UC3,Scalar(218,112,214));
// 将内存中的t0图像保存为当前目录下的t0.jpg文件
imwrite("t0.jpg",t0);
// 创建256行×256列的3通道8位无符号彩色图像,仅分配内存,像素值为内存随机值
Mat t1 = Mat(256,256,CV_8UC3);
// 对整张图像统一赋值为纯蓝色(B=255, G=0, R=0)
t1 = Scalar(255,0,0);
// 将t1图像保存为t1.jpg
imwrite("t1.jpg",t1);
// 创建全零矩阵(全黑图像),尺寸为宽300×高300,3通道8位彩色
// 注意:Size(宽, 高) 参数顺序为先宽后高,与Mat构造函数先行后列顺序相反
Mat t2 = Mat::zeros(Size(300,300),CV_8UC3);
// 将全黑图像保存为t2.jpg
imwrite("t2.jpg",t2);
// 创建全1矩阵,尺寸为宽300×高300,3通道8位彩色
// 8位图像中像素值1接近全黑,肉眼几乎无法区分;该方法多用于浮点矩阵运算
Mat t3 = Mat::ones(Size(300,300),CV_8UC3);
// 将全1图像保存为t3.jpg
imwrite("t3.jpg",t3);
// 仅分配300×300的3通道8位彩色图像内存,不初始化像素值
// 像素内容为内存残留的随机数据,保存后为噪点乱码图像
Mat t4 = Mat(Size(300,300), CV_8UC3);
// 将未初始化的图像保存为t4.jpg
imwrite("t4.jpg",t4);
return 0;
}
命名空间
using namespace cv;
using namespace std;
using namespace cv:OpenCV 所有类和函数都归属于cv命名空间,写了之后代码里可以直接写Mat、imwrite,不用每次都写全称cv::Mat、cv::imwrite。using namespace std:标准库命名空间,同理不用写std::cout。
主函数:5 种图像创建方式详解
OpenCV 默认彩色图是 BGR 通道顺序 (不是常规的 RGB),Scalar(B, G, R) 对应蓝、绿、红三个通道,像素值范围 0~255。
4.1. 实现Mat构造,并保存到本地
Mat t0 = Mat(300,300,CV_8UC3,Scalar(218,112,214));
imwrite("t0.jpg",t0);
这指的是创建一个width:300,height:300,三通道的灰度图像, 粉色的图像218
4.2. 利用**Mat(Size size, int type)**构造生成矩阵数据,并保存到本地
Mat t1 = Mat(256,256,CV_8UC3);
t1 = Scalar(255,0,0);
imwrite("t1.jpg",t1);
这指的是创建一个width:256,height:256,三通道的图像。
然后再用t1 = Scalar(255,0,0);把矩阵变成蓝色
最后把矩阵保存到本地
4.3. 利用**Mat::zeros(rows,cols,type)**构造生成矩阵数据,并保存到本地
Mat t2 = Mat::zeros(Size(300,300),CV_8UC3);
imwrite("t2.jpg",t2);
利用zeros去创建矩阵,ZROS相当于创建一张黑色的图片,每个像素通道为0,并且Scalar(0,0,0)。
然后把图片保存到本地
4.4. 利用**Mat::ones(rows,cols,type)**构造生成矩阵数据,并保存到本地
Mat t3 = Mat::ones(Size(300,300),CV_8UC3);
imwrite("t3.jpg",t3);
利用ones去创建矩阵,ONES相当于每个像素第一个通道为1,后面两个通道为0,相当于Scalar(1,0,0))
然后把图片保存到本地
4.5.仅分配内存,不初始化
Mat t4 = Mat(Size(300,300), CV_8UC3);
imwrite("t4.jpg",t4);
- 只申请 300×300 的内存空间,不对像素做任何赋值;
- 像素值是内存里残留的随机数据,保存出来的图片是噪点、花屏的乱码效果,没有实际意义,一般不这么写。
运行验证:交叉编译出可执行文件放到板子运行,执行后当前目录生成 5 张 jpg 图片,就代表 OpenCV 核心、imgcodecs、imgproc 模块都工作正常。如果上篇博客中的库没完全移植进板子里面,通过报错找到缺少的库并移植进去。