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 区域裁剪与坐标。