opencv中mat深拷贝和浅拷贝
1. 浅拷贝(Shallow Copy)
特点:
共享数据内存,新对象和原对象指向同一块内存数据。
修改任一对象的数据会影响另一个对象(因为内存共享)。
高效(仅复制矩阵头信息,不复制实际数据)。
实现方式:
直接赋值:
复制代码
cv::Mat img1 = imread("image.jpg");
cv::Mat img2 = img1; // 浅拷贝
使用 clone() 的误用 :
若对浅拷贝后的对象调用 clone(),仍需注意原对象是否被修改。
示例:
复制代码
cv::Mat mat1 = (cv::Mat_
cv::Mat mat2 = mat1; // 浅拷贝
mat2.at
std::cout << mat1 << std::endl; // 输出 [99, 2; 3, 4]
2. 深拷贝(Deep Copy)
特点:
独立分配内存,新对象和原对象完全隔离。
修改任一对象不会影响另一个对象。
开销较大(需复制全部数据)。
实现方式:
clone() 方法:
复制代码
cv::Mat img1 = imread("image.jpg");
cv::Mat img2 = img1.clone(); // 深拷贝
copyTo() 方法:
复制代码
cv::Mat img2;
img1.copyTo(img2); // 深拷贝
示例:
复制代码
cv::Mat mat1 = (cv::Mat_
cv::Mat mat2 = mat1.clone(); // 深拷贝
mat2.at
std::cout << mat1 << std::endl; // 输出 [1, 2; 3, 4]
3. 关键区别总结
特性
浅拷贝
深拷贝
内存共享
是(修改互相影响)
否(数据独立)
性能
高效(仅复制矩阵头)
较慢(复制全部数据)
实现方法
= 赋值
clone() 或 copyTo()
适用场景
只读操作或临时引用
需独立修改数据时
4. 特殊情况与注意事项
(1) ROI(Region of Interest)的浅拷贝
通过 cv::Mat roi = img(cv::Rect(x,y,w,h)) 创建的 ROI 是浅拷贝。
修改 ROI 会影响原图:
复制代码
cv::Mat image = imread("image.jpg");
cv::Mat roi = image(cv::Rect(0,0,100,100)); // ROI 浅拷贝
roi.setTo(0); // 原图中对应区域也会变黑!
(2) copyTo() 的掩膜(Mask)功能
copyTo() 可结合掩膜实现选择性复制:
复制代码
cv::Mat dst;
src.copyTo(dst, mask); // 仅复制 mask 非零区域
(3) 多通道数据的拷贝
深拷贝会复制所有通道数据,保持完整独立性:
复制代码
cv::Mat color_img = imread("color.jpg");
cv::Mat deep_copy = color_img.clone(); // 所有通道独立
5. 如何选择拷贝方式?
用浅拷贝:
需要快速传递数据且不修改内容时(如函数参数传递只读数据)。
操作 ROI 时(避免内存重复分配)。
用深拷贝:
需独立修改数据时(如滤波、变换等操作)。
避免函数内修改影响外部数据时。
代码验证工具
可以通过以下代码检查两个矩阵是否共享内存:
复制代码
bool isSameData(const cv::Mat& a, const cv::Mat& b) {
return a.data == b.data; // 返回 true 表示浅拷贝
}
掌握深/浅拷贝的区别能有效避免 OpenCV 中的内存错误和逻辑问题!