OpenCV图像的内存存储

OpenCV使用内存存储器(memory storage)来统一管理各种动态的内存.内存存储器在底层被实现为一个有许多相同大小的内存块组成的双向链表,通过这种结构,OpenCV可以从内存存储器中快速的分配内存或将内存返回给内存存储器.

1.数据结构

cvMemStorage结构体定义

[cpp]  view plain copy
  1. typedef struct CvMemStorage    
  2. {    
  3.     int signature;    
  4.     CvMemBlock* bottom;           /* First allocated block.                   */    
  5.     CvMemBlock* top;              /* Current memory block - top of the stack. */    
  6.     struct  CvMemStorage* parent; /* We get new blocks from parent as needed. */    
  7.     int block_size;               /* Block size.                              */    
  8.     int free_space;               /* Remaining free space in current block.   */    
  9. }    
  10. CvMemStorage;    

       内存存储器是一个用来存储诸如序列,轮廓,图形和子划分等动态增长数据结构的底层结构.它由一系列同等大小的内存块构成,呈列表型.其中,bottom域指列首,top域指当前指向的块,但未必是列尾.在bottom和投票之间的所有块空间(包括bottom,但不包括top)被完全占据;在top和列尾之间所有的块空间(包括列尾,但不包括top)则是空的;而top块空间本身则被部分占据.free_space指top块内剩余的空字节数.

      新分配的内存缓冲区(显示的通过函数cvMemStorageAlloc分配,或隐式地通过高级函数cvSeqPush和cvGraphAddEdge等分配)总是起始于当前块(即top块)中剩余的那部分空间,但前提条件是剩余的部分有足够大小的分配空间.分配后,free_space就减少了新分配的那部分内存大小,以及一些用来保存适当类型的附加大小.当top块的剩余空间无法满足被分配的块(缓冲区)大小时,top块的下一个存储块被置为当前块(新的top块),而free_space被置为先前分配的整个块的大小.

       如果已经不存在空的存储块(即top块已是列尾),则必须再分配一个新的块(或从parent那里继承,见函数cvCreatChildMemStorage)并将该块加到列尾上去.于是,存储器(memory storage)就如同栈(stack)一样,bottom指向栈底,(top, free_space)对指向栈顶.栈顶可通过函数cvSaveMemStoragePos保存,通过函数cvRestoreMemStoragePos恢复指向,通过函数ClearStorage重置.

CvMemBlock结构体定义

[cpp]  view plain copy
  1. typedef struct CvMemBlock    
  2. {    
  3.     struct CvMemBlock*  prev;    
  4.     struct CvMemBlock*  next;    
  5. }    
  6. CvMemBlock;   

      CvMemBlock代表一个单独的内存存储块结构.内存存储块中的实际数据存储在header块(即一个以头指针head指向的块,该块不存储数据)之后,于是,内存块的第i字节可以通过表达式((char*)(mem_block_ptr+1))[i]获得.然而,通常没必要直接获得存储结构的域.

CvMemStoragePos结构体定义
[cpp]  view plain copy
  1. typedef struct CvMemStoragePos    
  2. {    
  3.     CvMemBlock* top;    
  4.     int free_space;    
  5. }    
  6. CvMemStoragePos;    

      此结构保存栈顶的地址.栈顶可以通过函数cvSaveMemStoragePos保存,也可以通过函数cvRestoreMemStoragePos恢复.

2.数据操作

(1)CreaMemStorage
功能:
     函数cvCreateMemStorage创建一内存块并返回指向块首的指针.
格式:
     CvMemStorage* cvCreateMemStorage(int block_size = 0);
参数:
      block_size: 存储块的大小,以字节表示.如果某块大小为0字节,则将该值设置为默认值.当前默认大小为64K字节.
说明:

      起初,创建的存储块是空的.头部header的所有值域除了block_size外均为0.

(2)CreateChildMemStorage
功能:
函数cvCreateChildMemStorage创建子内存块
格式
cvMemStorage* cvCreateChildMemStorage(CvMemStorage* parent);
参数:
parent 父内存块
说明:
除了内存分配/释放机制不同外,函数cvCreateChildMemStorage将创建一类似于普通内存块的子内存块.当一个子存储块需要一个新块加入时,它就试图从parent那里得到这样一个块.如果parent中还有未被占据空间的那些块中的第一个块是可获得的,就获取第一个块,依此类推,然后再将该块从parent那里去除.如果不存在这样的块,则parent或者分配一个,或者从他自己的parent(即parent的parent)那里借来一个.换句话说,完全有可能形成一个链或者更为复杂的结构,其中的内存存储块互为child-parent(父子)关系.当子存储结构被释放或者清除,他就把所有的块还给各自的parent.再其他方面,子存储结构与普通存储结构相同.
子存储结构在下列情况中非常有用.例如,如果用户需要处理存储在某个块中的动态数据,然后再将处理结果放回该块中的情况.再如,当使用了最简单的方法处理之后,临时数据作为输入和输出数据被存放在同一个存储块中的情况,于是该存储块看上去就类似于图4-2中处理后的样子.
OpenCV图像的内存存储_第1张图片

结果,在存储块中出现了垃圾(临时数据).然而,如果在开始处处理数据前就先建立一个子存储块,且将临时数据写入子存储块中并在最后释放子存储块,那么最终在源/目的存储块中就不会出现垃圾,于是该存储块看上去应该是如图4-3所示形式.

OpenCV图像的内存存储_第2张图片
(3)ReleaseMemStorage

功能:

函数cvReleaseMemStorage释放内存块

格式:

void cvReleaseMemStorage(CvMemStorage** storage);

参数:

storage 指向被释放了的存储块的指针

说明:

函数cvReleaseMemStorage先释放所有的存储(内存)块或将它们返回给各自的parent(如果需要的话).然后在释放header块[释放头指针head指向的块执行语句free(head)]并清楚指向该块的指针(执行语句head=NULL).在释放parent块之前,必须先清楚各自的child块.

(4)ClearMemStorage

功能:

函数cvClearMemStorage清空内存存储块

格式:

void cvClearMemStorage(CvMemStorage* storage);

参数:

storage 内存存储块

说明:

函数cvClearMemStorage将存储块的top置于存储块的头部(注意,应清空存储块中的存储内容).次函数并不释放内存,仅清空内存.假设该内存块有一个父内存块(即存在一内存块与其有父子关系),则次函数将所有块放回给其父内存块.

(5)MemStorageAlloc

功能

函数cvMemStorageAlloc在存储块中分配一内存缓冲区

格式:

void* cvMemStorageAlloc(CvMemStorage* storage,size_t size);

参数

storage 内存块

size 缓冲区大小

说明

分配的缓冲区大小不能超过内存块大小,否则将导致运行错误.缓冲区的地址以CV_STRUCT_ALIGN[当前为sizeof(double)]的整数倍来调整.

(6)MemStorageAllocString

功能

函数cvMemStorageAllocString在存储块中分配一文本字符串

格式:

CvString cvMemStorageAllocString(CvMemStorage* storage,const char* ptr,int len = -1);

参数:

stoage 存储块.

ptr 字符串

len  字符串长度(不包括结束符'\0').如果次参数为负数,则函数计算该字符串的长度

说明:

函数cvMemStorageAlloString在存储块中创建一字符串的备份,并返回如下结构

typedef struct CvString

{

     int  len;

    char*  ptr;

}CvString;

该结构包含字符串长度(该长度可以通过用户传递,也可以通过计算得到)和指向被复制了的字符串指针.

(7)SaveMemStoragePos

功能:

函数cvSaveMemStoragePos保存内存块的地址

格式:

void cvSaveMemStoragePos(const CvMemStorage* storage,CvMemStoragePos* pos);

参数:

storage 内存块.

pos  内存块的顶部位置

说明:

函数cvSaveMemStoragePos将内存块的当前地址保存到参数pos中.函数cvRestoreMemStoragePos可获取该地址.

(8)RestoreMemStoragePos

功能:

函数cvRestoreMemStoragePos恢复内存块的地址

格式:

void cvRestoreMemStoragePos(const CvMemStorage* storage,CvMemStoragePos* pos);

参数:

storage 内存块.

pos  新的内存块地址

说明:

函数cvRestoreMemStoragePos通过参数pos恢复内存块的地址.此函数与函数cvClearMemStorage是释放被占用内存块的唯一方法.

注意:没有方法可以用来释放内存块中被占用的部分内存.

你可能感兴趣的:(OpenCV图像的内存存储)