OpenCV Mat类型
OpenCV Mat类型
OpenCV的Mat类型是图像处理和计算机视觉中最核心的数据结构,用于高效存储和操作多维数组(尤其是二维图像)。
核心特性
- 内存自动管理:
Mat使用引用计数机制,自动释放不再使用的内存。 - 多维数组支持:支持二维图像、三维体积数据,甚至更高维度的矩阵。
- 灵活的数据类型:支持多种数据类型(如
uchar,float,double)和多通道数据(如RGB图像的3通道)。 - 零拷贝机制:通过“浅拷贝”共享数据,避免不必要的内存复制,提升效率。
Mat的结构
每个Mat对象包含两部分:
- 矩阵头(Header):存储矩阵的元信息(尺寸、数据类型、通道数等)。
- 数据指针(Data Pointer):指向实际存储像素数据的连续内存块。
cv::Mat mat; // 创建一个空的矩阵头(无数据)
创建Mat对象
常见的格式与使用场景
| 常见格式 | 使用场景 |
|---|---|
| CV_8UC1 | 灰度图、图像掩码 |
| CV_8UC3 | 摄像头采集 |
| CV_8UC4 | 透明图层叠加 |
| CV_16UC1 | 深度图 |
| CV_32FC1 | Sobel边缘检测的梯度幅值 |
| CV_32FC3 | YUV到RGB的高精度色彩空间转换 |
构造函数指定尺寸和类型
- 构造函数:
cv::Mat(行数, 列数, 格式) - 注意在通常以宽高形容时,宽指的是列数,高指的是行数;
- 如果用宽高来形容,则应为:
cv::Mat(高, 宽, 类型)
- 如果用宽高来形容,则应为:
// 创建一个640x480的3通道8位无符号整数矩阵(BGR图像)
cv::Mat img(480, 640, CV_8UC3);
// 创建一个100x100的单通道8位无符号整数矩阵(灰度图像)
cv::Mat img_gray(100, 100, CV_8UC1);
使用create()方法
create方法会释放掉先前分配的内存,再重新分配
cv::Mat mat;
mat.create(480, 640, CV_8UC3); // 重新分配内存(若之前mat已分配内存,则释放之前分配的内存)
初始化特殊矩阵
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)
- 语法:
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);获取当前行列像素的指针
// 获取行指针访问
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通道
// 访问单通道像素(灰度)
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>(); - 安全但效率不高
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
}

浙公网安备 33010602011771号