2.3.2自动内存管理 

1.创建矩阵

创建一个大小为 8MB 的大矩阵(1字节为8位,64字节为8位)
1000 * 1000 = 1000000 个元素的矩阵 A,数据类型为 64 位浮点数(CV_64F) 

Mat A(1000, 1000, CV_64F);

2.为同个矩阵创建另一个头

这是一个即时操作,与矩阵的大小无关
Mat B 是矩阵 A 的一个引用,它们指向同一块内存区域,不会复制矩阵的数据

如果确实需要复制矩阵的数据,可以使用 clone() 方法,如 Mat B = A.clone(); ,这样会创建一个新的矩阵,其数据与 A 相同,但存储在不同的内存区域

 Mat B = A;Mat B = A.clone(); 
数据内容不复制原矩阵数据复制原矩阵的数据
储存区域共享同一块数据内存存储在不同的内存区域
Mat B = A;

3. 为 A 的第 3 行创建另一个头

同样,也不会复制数据
Mat C 是矩阵 A 第 3 行的引用,C 和 A 的第 3 行共享同一块内存

Mat C = B.row(3);

4.创建矩阵的一个独立副本

Mat D 是矩阵 B(也就是矩阵 A)的一个完整副本,会分配新的内存来存储数据

Mat D = B.clone();

 5.将 B 的第 5 行复制到 C

也就是将 A 的第 5 行复制到 A 的第 3 行
由于 C 引用的是 A 的第 3 行,所以这一操作会修改 A 的第 3 行内容

B.row(5).copyTo(C);

6. A 和 D 共享数据

修改后的 A 版本仍然由 B 和 C 引用
此时 A 不再引用原来的数据,而是和 D 指向同一块内存,而 B 和 C 仍然引用原来的 A 数据

A = D;

6. 现在让 B 成为一个空矩阵(即不引用任何内存缓冲区)

修改后的 A 版本仍然会被 C 引用
尽管 C 只是原始 A 的一行
调用 release 方法后,B 不再引用原来的内存当该内存没有其他引用时,会被释放

B.release();
补充:引用计数机制基础

Mat 类内部维护一个引用计数(refcount,用于记录有多少 Mat 对象引用同一数据内存。

当创建一个 Mat 对象并分配内存时,该内存块的引用计数初始化为 1。

当有新的 Mat 对象引用这块内存时,引用计数加 1;

当一个 Mat 对象不再引用这块内存时,引用计数减 1。

当引用计数变为 0 时,意味着没有任何 Mat 对象引用这块内存,此时会自动释放该内存

7.对 C 进行完整复制

这个大的修改后的矩阵将被释放,因为没有任何人引用它了
C 现在是它自身的一个副本,原来的引用被断开,当原来的内存没有其他引用时,会被释放

C = C.clone();

总结 

以上七条代码主要展示了 OpenCV 中 Mat 对象的内存管理和数据引用机制

Mat 对象包含一个头(header)和指向实际数据的指针,多个 Mat 对象可以引用同一块内存,通过不同的操作可以控制数据的共享和复制,从而提高内存使用效率

!当没有 Mat 对象引用某块内存时,这块内存会被自动释放。 

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐