OpenCV Mat数据地址异常咨询:赋值后新创建Mat地址未变更
OpenCV Mat赋值后重新创建数据地址未变化的原因及解决方法
原因分析
- Mat的引用计数特性:OpenCV的
cv::Mat采用引用计数机制,赋值操作仅复制Mat的头信息(包括数据指针、尺寸、类型等),不会拷贝底层像素数据。步骤3中sobel_img_ = local_mat执行后,sobel_img_会放弃原有的内存(步骤2创建的内存块),转而与local_mat共享同一块内存,该内存的引用计数从1变为2。 - 内存池复用优化:OpenCV内置内存池管理内存分配,当释放的内存块大小、类型与新申请的内存完全匹配时,会优先复用该内存块。步骤3执行时,
sobel_img_原有的内存因引用计数归零被释放回内存池。若步骤4创建的新Mat尺寸、类型与释放的内存块一致,内存池会直接复用该内存;若你遇到地址与local_mat相同的情况,大概率是local_mat的内存已因作用域结束等原因被释放,内存池复用了这块地址——这属于正常的内存管理行为,并非代码错误。
解决方法
若你需要确保每次创建Mat都使用全新的独立内存,可通过以下方式实现:
- 使用
clone()方法:创建Mat的深拷贝,完全复制底层数据,生成独立的内存块:sobel_img_ = local_mat.clone(); // 深拷贝,不共享内存 - 使用
copyTo()方法:将数据复制到目标Mat,若目标Mat尺寸、类型不匹配会自动重新分配内存:local_mat.copyTo(sobel_img_); - 显式释放内存后重新赋值:先调用
release()释放当前Mat关联的内存,再创建新Mat:sobel_img_.release(); sobel_img_ = cv::Mat::eye(cv::Size(1000, 1000), CV_8UC1); - 直接构造新Mat对象:避免赋值操作,直接通过构造函数初始化新的独立Mat:
cv::Mat sobel_img_(cv::Size(1000, 1000), CV_8UC1, cv::Scalar(1)); // 生成与eye等效的8UC1矩阵
内容的提问来源于stack exchange,提问作者Soonmyun Jang
相关产品推荐
相关产品推荐

