OpenCV Mat类型

风陵南·2025-02-27 10:19·6 次阅读

OpenCV Mat类型

OpenCV Mat类型

OpenCV的Mat类型是图像处理和计算机视觉中最核心的数据结构,用于高效存储和操作多维数组(尤其是二维图像)。

核心特性#

  • 内存自动管理Mat使用引用计数机制,自动释放不再使用的内存。
  • 多维数组支持:支持二维图像、三维体积数据,甚至更高维度的矩阵。
  • 灵活的数据类型:支持多种数据类型(如uchar,float,double)和多通道数据(如RGB图像的3通道)。
  • 零拷贝机制:通过“浅拷贝”共享数据,避免不必要的内存复制,提升效率。

Mat的结构#

每个Mat对象包含两部分:

  • 矩阵头(Header):存储矩阵的元信息(尺寸、数据类型、通道数等)。
  • 数据指针(Data Pointer):指向实际存储像素数据的连续内存块。
Copy
cv::Mat mat; // 创建一个空的矩阵头(无数据)

创建Mat对象#

常见的格式与使用场景#

常见格式 使用场景
CV_8UC1 灰度图、图像掩码
CV_8UC3 摄像头采集
CV_8UC4 透明图层叠加
CV_16UC1 深度图
CV_32FC1 Sobel边缘检测的梯度幅值
CV_32FC3 YUV到RGB的高精度色彩空间转换

构造函数指定尺寸和类型#

  • 构造函数cv::Mat(行数, 列数, 格式)
  • 注意在通常以宽高形容时,指的是列数指的是行数
    • 如果用宽高来形容,则应为:cv::Mat(高, 宽, 类型)
Copy
// 创建一个640x480的3通道8位无符号整数矩阵(BGR图像)
cv::Mat img(480, 640, CV_8UC3);
// 创建一个100x100的单通道8位无符号整数矩阵(灰度图像)
cv::Mat img_gray(100, 100, CV_8UC1);

使用create()方法#

create方法会释放掉先前分配的内存,再重新分配

Copy
cv::Mat mat;
mat.create(480, 640, CV_8UC3); // 重新分配内存(若之前mat已分配内存,则释放之前分配的内存)

初始化特殊矩阵#

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){
// 访问BGR通道值
row_ptr[col][0] = 255; // Blue通道
row_ptr[col][1] = 0; // Green通道
row_ptr[col][2] = 0; // Red通道
}
}
// 直接获取像素指针
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);
// 访问BGR通道值
pix->val[0] = 255; // Blue通道
pix->val[1] = 0; // Green通道
pix->val[2] = 0; // Red通道
}
}

使用at()方法#

  • 效率与ptr()近似
  • mat.at<uchar>(row, col); 单通道
  • mat.at<cv::Vec3b>(row, col); BGR通道
Copy
// 访问单通道像素(灰度)
uchar pixel_value = gray_img.at<uchar>(50, 50);
// 访问多通道像素(BGR)
cv::Vec3b &pixel = img.at<cv::Vec3b>(50, 50); // &引用访问无需拷贝提高效率
pixel[0] = 255; // B
pixel[1] = 0; // G
pixel[2] = 0; // R

使用迭代器(安全)#

  • 可以不用管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
}
posted @   风陵南  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示
目录