数据存储

来源:互联网 发布:fifa online3数据库15 编辑:程序博客网 时间:2024/04/30 15:33

OpenCV提供了一种机制来序列化(serialize)和去序列化(de-serialize)其各种数据类型,可以从磁盘中按YAML或XML格式读/写。在第4章中,我们将专门介绍存储和调用常见的对象IplImages的函数(cvSaveImage()和cvLoadImage())。此外,第4章将讨论读/写视频的特有函数:可以从文件或者摄影机中读取数据的函数cvGrabFrame()以及写操作函数cvCreateVideoWriter()和cvWriteFrame()。本小节将侧重于一般对象的永久存储:读/写矩阵、OpenCV结构、配置与日志文件。

首先,我们从有效且简便的OpenCV矩阵的保存和读取功能函数开始。函数是cvSave()和cvLoad()。例3-15展示了如何保存和读取一个5×5的单位矩阵(对角线上是1,其余地方都是0)。

例3-15:存储和读取CvMat

  1. CvMat A = cvMat( 5, 5, CV_32F, the_matrix_data );  
  2.  
  3. cvSave( "my_matrix.xml", &A );  
  4. . . .  
  5. // to load it then in some other program use …  
  6. CvMat* A1 = (CvMat*) cvLoad( "my_matrix.xml" ); 

CxCore参考手册中有整节内容都在讨论数据存储。首先要知道,在OpenCV中,一般的数据存储要先创建一个CvFileStorage结构(如例3-16)所示,该结构将内存对象存储在一个树形结构中。然后通过使用CV_STORAGE_READ参数的cvOpenFileStorage()从磁盘读取数据,创建填充该结构,也可以通过使用CV_STORAGE_WRITE的cvOpenFileStorage()创建并打开CvFileStorage写数据,而后使用适当的数据存储函数来填充它。在磁盘上,数据的存储格式为XML或者YAML。

例3-16:CvFileStorage结构,数据通过CxCore数据存储函数访问

  1. typedef struct CvFileStorage  
  2. {  
  3.     ...      // hidden fields  
  4. } CvFileStorage; 

CvFileStorage树内部的数据是一个层次化的数据集合,包括标量、CxCore对象(矩阵、序列和图)以及用户定义的对象。

假如有一个配置文件或日志文件。配置文件告诉我们视频有多少帧(10),画面大小(320×240)并且将应用一个3×3的色彩转换矩阵。例3-17展示了如何从磁盘中调出cfg.xml文件。

例3-17:往磁盘上写一个配置文件cfg.xml

  1. CvFileStorage* fs = cvOpenFileStorage(  
  2.   "cfg.xml",  
  3.   0,  
  4.   CV_STORAGE_WRITE  
  5. );  
  6. cvWriteInt( fs, "frame_count", 10 );  
  7. cvStartWriteStruct( fs, "frame_size", CV_NODE_SEQ );  
  8. cvWriteInt( fs, 0, 320 );  
  9. cvWriteInt( fs, 0, 200 );  
  10. cvEndWriteStruct(fs);  
  11. cvWrite( fs, "color_cvt_matrix", cmatrix );  
  12. cvReleaseFileStorage( &fs ); 

请留意这个例子中的一些关键函数。我们可以定义一个整型变量通过cvWritelnt()向结构中写数据。我们也可以使用cvStartWriteStruct()来创建任意一个可以任选一个名称(如果无名称请输入0或NULL)的结构。这个结构有两个未命名的整型变量,使用cvEndWriteStruct()结束编写结构。如果有更多的结构体,我们用相似的方法来解决;这种结构可以进行任意深度的嵌套。最后,我们使用cvWrite()编写处色彩转换矩阵。将这个相对复杂的矩阵程序与例3-15中简单的cvSave()程序进行对比。便会发现cvSave()是cvWrite()在只保存一个矩阵时的快捷方式。当写完数据后,使用cvReleaseFileStorage()释放CvFileStorage句柄。例3-18显示了XML格式的输出内容。

例3-18:磁盘中的cfg.xml文件

  1. <?xml version="1.0"?> 
  2. <opencv_storage> 
  3. <frame_count>10</frame_count> 
  4. <frame_size>320 200</frame_size> 
  5. <color_cvt_matrix type_id="opencv-matrix"> 
  6.   <rows>3</rows> <cols>3</cols> 
  7.   <dt>f</dt> 
  8.   <data>...</data></color_cvt_matrix> 
  9. </opencv_storage> 

我们将会在例3-19中将这个配置文件读入。

例3-19:磁盘中的cfg.xml文件

  1. CvFileStorage* fs = cvOpenFileStorage(  
  2.   "cfg.xml",  
  3.   0,  
  4.   CV_STORAGE_READ  
  5. );  
  6.  
  7. int frame_count = cvReadIntByName(  
  8.   fs,  
  9.   0,  
  10.   "frame_count",  
  11.   5 /* default value */  
  12. );  
  13.  
  14. CvSeq* s = cvGetFileNodeByName(fs,0,"frame_size")->data.seq;  
  15.  
  16. int frame_width = cvReadInt(  
  17.   (CvFileNode*)cvGetSeqElem(s,0)  
  18. );  
  19.  
  20. int frame_height = cvReadInt(  
  21.   (CvFileNode*)cvGetSeqElem(s,1)  
  22. );  
  23.  
  24. CvMat* color_cvt_matrix = (CvMat*) cvReadByName(  
  25.   fs,  
  26.   0,  
  27.   "color_cvt_matrix"  
  28. );  
  29.  
  30. cvReleaseFileStorage( &fs ); 

在阅读时,我们像例3-19中那样用cvOpenFileStorage()打开XML配置文件。然后用cvReadlntByName()来读取frame_count,如果有没有读到的数,则赋一个默认值。在这个例子中默认的值是5。然后使用cvGetFileNodeByName()得到结构体frame_size。在这里我们用cvReadlnt()读两个无名称的整型数据。随后使用cvReadByName()读出我们已经定义的色彩转换矩阵。 将本例与例3-15中的cvLoad()进行对比。如果我们只有一个矩阵要读取,那么可以使用cvLoad(),但是如果矩阵是内嵌在一个较大的结构中,必须使用cvRead()。最后,释放CvFileStorage结构。

数据函数存储与CvFileStorage结构相关的表单列在表3-16中。想了解更多细节,请查看CxCore手册。

表3-16:数据存储函数

函数名称

描述

打开并释放

 

cvOpenFileStorage

为读/写打开存储文件

cvReleaseFileStorage

释放存储的数据

写入

 

cvStartWriteStruct

开始写入新的数据结构

cvEndWriteStruct

结束写入数据结构

cvWriteInt

写入整数型

cvWriteReal

写入浮点型

cvWriteString

写入字符串

cvWriteComment

写一个XML或YAML的注释字串

cvWrite

写一个对象,例如CvMat

cvWriteRawData

写入多个数值

cvWriteFileNode

将文件节点写入另一个文件存储器

读取

 

cvGetRootFileNode

获取存储器最顶层的节点

cvGetFileNodeByName

在映图或存储器中找到相应节点

cvGetHashedKey

为名称返回一个惟一的指针

cvGetFileNode

在映图或文件存储器中找到节点

cvGetFileNodeName

返回文件的节点名

cvReadInt

读取一个无名称的整数型

cvReadIntByName

读取一个有名称的整数型

cvReadReal

读取一个无名称的浮点型

续表

函数

描述

cvReadRealByName

读取一个有名称的浮点型

cvReadString

从文件节点中寻找字符串

cvReadStringByName

找到一个有名称的

文件节点并返回它

cvRead

将对象解码并返回它的指针

cvReadByName

找到对象并解码

cvReadRawData

读取多个数值

cvStartReadRawData

初始化文件节点序列的读取

cvReadRawDataSlice

读取文件节点的内容

原创粉丝点击