OpenCV Mat类型
OpenCV的Mat
类型是图像处理和计算机视觉中最核心的数据结构,用于高效存储和操作多维数组(尤其是二维图像)。
核心特性#
- 内存自动管理:
Mat
使用引用计数机制,自动释放不再使用的内存。
- 多维数组支持:支持二维图像、三维体积数据,甚至更高维度的矩阵。
- 灵活的数据类型:支持多种数据类型(如
uchar
,float
,double
)和多通道数据(如RGB图像的3通道)。
- 零拷贝机制:通过“浅拷贝”共享数据,避免不必要的内存复制,提升效率。
Mat的结构#
每个Mat
对象包含两部分:
- 矩阵头(Header):存储矩阵的元信息(尺寸、数据类型、通道数等)。
- 数据指针(Data Pointer):指向实际存储像素数据的连续内存块。
Copy
创建Mat对象#
常见的格式与使用场景#
常见格式 |
使用场景 |
CV_8UC1 |
灰度图、图像掩码 |
CV_8UC3 |
摄像头采集 |
CV_8UC4 |
透明图层叠加 |
CV_16UC1 |
深度图 |
CV_32FC1 |
Sobel边缘检测的梯度幅值 |
CV_32FC3 |
YUV到RGB的高精度色彩空间转换 |
构造函数指定尺寸和类型#
- 构造函数:
cv::Mat(行数, 列数, 格式)
- 注意在通常以宽高形容时,宽指的是列数,高指的是行数;
- 如果用宽高来形容,则应为:
cv::Mat(高, 宽, 类型)
Copy
| |
| cv::Mat img(480, 640, CV_8UC3); |
| |
| cv::Mat img_gray(100, 100, CV_8UC1); |
使用create()
方法#
create
方法会释放掉先前分配的内存,再重新分配
Copy
| cv::Mat mat; |
| mat.create(480, 640, CV_8UC3); |
初始化特殊矩阵#
Copy
| cv::Mat zeros = cv::zeros(100, 100, CV_8UC1); // 全零矩阵 |
| cv::Mat ones = cv::ones(100, 100, CV_8UC1); // 全 1 矩阵 |
| cv::Mat eye = cv::eye(3, 3, CV_8UC1); // 单位矩阵 |
ROI感兴趣区域#
- 语法:
cv::Rect rect(起始x, 起始y, ROI宽, ROI高)
- 例:
cv::Rect rect(100, 100, 300, 300);
,从(100, 100)再取300*300的区域
- 注意:300, 300不是结束的x,y坐标
- 结束坐标应当是
x + ROI宽, y + ROI高
- 初始化mat
- 语法:
cv::Mat roi = mat(rect)
Copy
| cv::Mat mat = imread("1.png"); |
| cv::Rect rect(100, 100, 200, 200); |
| cv::Mat roi = mat(rect); |
| cv::namedWindow("roi", WINDOW_AUTOSIZE); |
| imshow("roi", roi); |
访问像素数据#
使用模板函数ptr()
访问行指针(高效)#
- 通过指针访问等同于直接地址访问,无需额外的拷贝操作
mat.ptr<cv::Vec3b>(row);
获取行指针
mat.ptr<cv::Vec3b>(row, col);
获取当前行列像素的指针
Copy
| |
| for(int row = 0; row < mat.rows; ++row){ |
| cv::Vec3b *row_ptr = mat.ptr<cv::Vec3b>(row); |
| for(int col = 0; col < mat.cols; ++col){ |
| |
| row_ptr[col][0] = 255; |
| row_ptr[col][1] = 0; |
| row_ptr[col][2] = 0; |
| } |
| } |
| |
| |
| for(int row = 0; row < mat.rows; ++row){ |
| for(int col = 0; col < mat.cols; ++col){ |
| cv::Vec3b *pix = mat.ptr<cv::Vec3b>(row, col); |
| |
| pix->val[0] = 255; |
| pix->val[1] = 0; |
| pix->val[2] = 0; |
| } |
| } |
使用at()
方法#
- 效率与
ptr()
近似
mat.at<uchar>(row, col);
单通道
mat.at<cv::Vec3b>(row, col);
BGR通道
Copy
| |
| uchar pixel_value = gray_img.at<uchar>(50, 50); |
| |
| cv::Vec3b &pixel = img.at<cv::Vec3b>(50, 50); |
| pixel[0] = 255; |
| pixel[1] = 0; |
| pixel[2] = 0; |
使用迭代器(安全)#
- 可以不用管mat的行列
- 语法:
auto it = mat.begin<cv::Vec3b>();
- 安全但效率不高
Copy
| cv::MatIterator_<cv::Vec3b> it = mat.begin<cv::Vec3b>(); |
| cv::MatIterator_<cv::Vec3b> end = mat.endMcv::Vec3b>(); |
| for(; it!= end; ++it){ |
| (*it)[0] = 255; // B |
| (*it)[1] = 0; // G |
| (*it)[2] = 0; // R |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!