跳转到内容
新建笔记

OpenCV Mat:共享数据、深拷贝与颜色通道

Mat 对象和像素数据是两件事

跳转到“Mat 对象和像素数据是两件事”

cv::Mat 包含尺寸、类型、步长等描述信息,以及像素数据的访问方式。通常,cv::Mat b = a 创建另一个 Mat 头并共享原数据;它既不是深拷贝,也不是 cv::Mat& b = a 这样的 C++ 引用声明。修改共享像素会同时从两个 Mat 中观察到。OpenCV Mat 教程

下例适用于配置好 OpenCV 4 的 C++ 工程,不依赖磁盘图片。

#include <opencv2/core.hpp>
#include <iostream>
int main() {
cv::Mat original(2, 3, CV_8UC3, cv::Scalar(0, 0, 0));
cv::Mat shared = original;
cv::Mat independent = original.clone();
shared.setTo(cv::Scalar(255, 0, 0));
std::cout << original.at<cv::Vec3b>(0, 0) << '\n';
std::cout << independent.at<cv::Vec3b>(0, 0) << '\n';
}

第一处像素为 [255, 0, 0],第二处仍为 [0, 0, 0]:clone() 复制了数据,因此独立图像不受修改影响。

为什么 Scalar(255) 显示蓝色

跳转到“为什么 Scalar(255) 显示蓝色”

OpenCV 常见彩色图像按 B、G、R 排列。cv::Scalar(255) 后续分量默认是 0,所以在三通道 BGR 图像中相当于 (255,0,0),即蓝色。白色应显式写成 cv::Scalar(255,255,255),或使用 cv::Scalar::all(255)。

CV_8UC3 表示每通道 8 位无符号数、每像素 3 通道。rows 是高度,cols 是宽度;访问 at(row,col) 时顺序是先纵向、后横向。

cv::Mat image = cv::imread("image.png", cv::IMREAD_COLOR);
if (image.empty()) {
// 处理路径、格式或读取失败;不要继续访问像素。
return 1;
}

这段读取需要包含 <opencv2/imgcodecs.hpp>。当前工作目录不一定是源代码目录,读取失败时先核对实际文件路径。

原截图展示的是“赋值后修改,两个窗口一起变色”,现已转为可复制例子。共享 ROI 的行为见 OpenCV 区域裁剪与坐标。