如何为OpenCV中Mat的所有子类实现按引用复制?
适用于所有OpenCV Mat子类的引用复制实现
你的需求是创建Mat子类(如MatOfKeyPoint)的引用副本,共享同一原生内存,同时保留引用计数管理(每个实例调用release()都会减少计数,避免内存泄漏)。之前用submat()的方式只能返回Mat类型,无法适配子类,下面提供通用解法:
OpenCV的Mat及其所有子类都基于原生的cv::Mat结构,引用计数由原生端维护。要实现子类的引用复制,核心是创建同类型的子类实例,并让它关联到同一个原生cv::Mat指针,同时增加引用计数。
Kotlin 通用扩展函数实现
import org.opencv.core.Mat inline fun <reified T : Mat> T.copyByReference(): T { // 获取当前Mat实例的原生对象地址 val nativeAddr = this.nativeObjAddr // 通过反射调用子类继承的protected构造方法(接收原生地址) val constructor = T::class.java.getDeclaredConstructor(Long::class.java) constructor.isAccessible = true val newInstance = constructor.newInstance(nativeAddr) return newInstance }
代码说明
- 获取原生地址:
nativeObjAddr是Mat类的继承属性,所有子类都能调用,用于获取底层cv::Mat的指针地址。 - 反射创建实例:OpenCV的
Mat类有一个protected的构造方法Mat(long addr),用于关联已有的原生cv::Mat对象,所有子类都继承了这个构造方法。通过反射打开访问权限,就能创建同类型的子类实例并关联到同一原生地址。 - 引用计数管理:调用该构造方法时,OpenCV底层会自动执行
cv::Mat的复制构造逻辑,增加引用计数。后续每个实例调用release()都会减少计数,当计数归0时,原生内存会被自动释放。
验证方法
- 复制后修改其中一个实例的数据,另一个实例的数据会同步变化(证明共享内存)。
- 分别调用两个实例的
release(),再尝试访问数据会触发异常(证明引用计数生效,内存已释放)。
注意事项
- 反射操作会有轻微性能开销,若需高频调用,可针对常用子类(如
MatOfKeyPoint)单独实现重载优化。 - OpenCV官方提供的所有Mat子类均继承了
Mat的long参数构造方法,可放心使用。
内容的提问来源于stack exchange,提问作者vatbub
相关产品推荐
相关产品推荐

