opencv之深拷贝及浅拷贝,IplImage装换为Mat

本文深入探讨了OpenCV中浅拷贝与深拷贝的概念,通过实例展示了如何在图像处理中应用这两种复制方式,并阐述了它们之间的关键区别。浅拷贝与深拷贝对于理解OpenCV中的图像操作至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、(1)  浅拷贝:  

Mat B;  

B = image  // 第一种方式  

Mat C(image); // 第二种方式

这两种方式称为浅copy,是由于它们有不同的矩阵头,但是它们共享内存空间,即指向一个矩阵。当图像矩阵发生变化时,两者相关联,都会变化。

(2)深拷贝

Mat B,C;  

B = image.clone();       // 第一种方式  

image.copyTo(C); // 第二种方式  

深拷贝是真正的copy了一个新的图像矩阵,此时image,B,C三者相互没有影响。

二、IplImage装换为Mat  

      IplImage* iplImage = cvLoadImage("E:\song.jpg",1);

     cv::Mat image2(iplImage,false);    //其中false为浅拷贝,而true为深拷贝,默认为false。IplImage 和image2共享同一份图像数据。

此时需要注意释放iplImage结构指向的内存时必须 调用函数:   cvReleaseImage(&iplImage);

当然opencv提供了另外一种指针类,无需手动释放,但现在已经不用了,可以使用它来封装IplImage指针: 

Ptr<IplImage> iplImage = cvLoadImage("E:\song.jpg",1); 

应该尽量避免使用这个废弃的数据结构,而是使用cv::Mat。

转自http://www.bubuko.com/infodetail-493981.html

opencv之深拷贝及浅拷贝,IplImage装换为Mat

<think>我们正在讨论OpenCVMat的row操作是否支持浅拷贝。根据OpenCV的文档,Mat::row函数会返回一个指向指定行的新Mat头,这是一种浅拷贝(即共享数据)。这意味着修改返回的Mat行也会影响原始矩阵,因为它们共享同一数据块。 引用[1]中提到了引用计数机制:当复制Mat头时,引用计数会增加;当头部被清理时,引用计数减少。当引用计数为零时,矩阵数据才会被释放。Mat::row创建的新Mat头会共享原始矩阵的数据,因此会增加引用计数。 因此,Mat::row是浅拷贝,不会复制数据本身。 下面是一个简单的示例代码,展示如何使用Mat::row并进行修改: ```cpp #include <opencv2/opencv.hpp> #include <iostream> int main() { // 创建一个3x3的矩阵,类型为CV_8UC1 cv::Mat mat = (cv::Mat_<uchar>(3,3) << 1,2,3,4,5,6,7,8,9); std::cout << "Original mat:\n" << mat << std::endl; // 获取第二行(索引为1)的浅拷贝 cv::Mat row = mat.row(1); // 修改这一行的值 row.setTo(0); // 原始矩阵也被修改了 std::cout << "After modification:\n" << mat << std::endl; return 0; } ``` 输出: ``` Original mat: [ 1, 2, 3; 4, 5, 6; 7, 8, 9] After modification: [ 1, 2, 3; 0, 0, 0; 7, 8, 9] ``` 从输出可以看出,修改通过Mat::row得到的行会同时修改原始矩阵。 如果你不希望修改原始矩阵,应该使用clone()方法进行深拷贝,例如: ```cpp cv::Mat row_copy = mat.row(1).clone(); ``` 这样,修改row_copy不会影响原始矩阵。 总结:Mat::row支持浅拷贝,返回的Mat头与原始矩阵共享数据。如果需要独立的副本,应使用clone()。 §§相关问题§§ 1. OpenCV中除了row,还有哪些方法返回的是浅拷贝Mat头? 2. 如何避免在OpenCV中意外修改原始矩阵数据? 3. OpenCV的引用计数机制在什么情况下会导致问题?</think>### OpenCVMat.row的浅拷贝支持 在OpenCV中,`Mat.row()` 函数**支持浅拷贝**(shallow copy),这是其默认行为。这意味着当你调用`mat.row(i)`时: 1. **共享数据内存**:返回的新`Mat`对象与原始矩阵共享同一数据块 2. **独立头部信息**:创建新的矩阵头部信息(包含行数、列数、数据类型等) 3. **引用计数增加**:OpenCV的引用计数机制会自动增加,防止数据被意外释放 #### 代码示例 ```cpp #include <opencv2/opencv.hpp> int main() { // 创建原始矩阵 cv::Mat original = (cv::Mat_<int>(3,3) << 1, 2, 3, 4, 5, 6, 7, 8, 9); // 获取第二行的浅拷贝 cv::Mat rowCopy = original.row(1); // 修改浅拷贝的数据 rowCopy.at<int>(0, 1) = 99; // 修改第1行第1列(实际是原始矩阵的[1][1]位置) // 原始矩阵也被修改 std::cout << "Modified original:\n" << original << std::endl; return 0; } ``` 输出: ``` Modified original: [1, 2, 3; 4, 99, 6; 7, 8, 9] ``` #### 关键特性: 1. **零拷贝操作**:不复制实际数据,性能高效 2. **内存安全**:引用计数机制确保只要任一Mat对象存在,数据就不会被释放[^1] 3. **视图特性**:返回的矩阵是原始矩阵的"视图",修改会影响原数据 #### 需要深拷贝时: 若需要独立副本,应显式调用`clone()`: ```cpp cv::Mat deepCopy = original.row(1).clone(); // 深拷贝 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值