在OpenCV中,采用FileStorage类进行数据持久化,可以采用XML或YAML格式存储数据。

将数据写入XML或YAML文件,可采用以下步骤:

1、创建FileStorage对象。可以调用构造函数 FileStorage::FileStorage(),并传入文件名参数;或者调用默认构造函数,然后调用 FileStorage::open()。

2、利用重载输出操作符<<,在operations.hpp中,输出操作符<<为模板函数:

template<typename _Tp> static inline FileStorage& operator << (FileStorage& fs, const _Tp& value)
{
if( !fs.isOpened() )
return fs;
if( fs.state == FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP )
CV_Error( CV_StsError, "No element name has been given" );
write( fs, fs.elname, value );
if( fs.state & FileStorage::INSIDE_MAP )
fs.state = FileStorage::NAME_EXPECTED + FileStorage::INSIDE_MAP;
return fs;
}

3、调用FileStorage::release(),关闭文件,并释放所有内存。

FileStorage在core.hpp定义如下:

class CV_EXPORTS_W FileStorage
{
public:
//! file storage mode
enum
{
READ=, //! read mode
WRITE=, //! write mode
APPEND=, //! append mode
MEMORY=,
FORMAT_MASK=(<<),
FORMAT_AUTO=,
FORMAT_XML=(<<),
FORMAT_YAML=(<<)
};
enum
{
UNDEFINED=,
VALUE_EXPECTED=,
NAME_EXPECTED=,
INSIDE_MAP=
};
//! the default constructor
CV_WRAP FileStorage();
//! the full constructor that opens file storage for reading or writing
CV_WRAP FileStorage(const string& source, int flags, const string& encoding=string());
//! the constructor that takes pointer to the C FileStorage structure
FileStorage(CvFileStorage* fs);
//! the destructor. calls release()
virtual ~FileStorage(); //! opens file storage for reading or writing. The previous storage is closed with release()
CV_WRAP virtual bool open(const string& filename, int flags, const string& encoding=string());
//! returns true if the object is associated with currently opened file.
CV_WRAP virtual bool isOpened() const;
//! closes the file and releases all the memory buffers
CV_WRAP virtual void release();
//! closes the file, releases all the memory buffers and returns the text string
CV_WRAP string releaseAndGetString(); //! returns the first element of the top-level mapping
CV_WRAP FileNode getFirstTopLevelNode() const;
//! returns the top-level mapping. YAML supports multiple streams
CV_WRAP FileNode root(int streamidx=) const;
//! returns the specified element of the top-level mapping
FileNode operator[](const string& nodename) const;
//! returns the specified element of the top-level mapping
CV_WRAP FileNode operator[](const char* nodename) const; //! returns pointer to the underlying C FileStorage structure
CvFileStorage* operator *() { return fs; }
//! returns pointer to the underlying C FileStorage structure
const CvFileStorage* operator *() const { return fs; }
//! writes one or more numbers of the specified format to the currently written structure
void writeRaw( const string& fmt, const uchar* vec, size_t len );
//! writes the registered C structure (CvMat, CvMatND, CvSeq). See cvWrite()
void writeObj( const string& name, const void* obj ); //! returns the normalized object name for the specified file name
static string getDefaultObjectName(const string& filename); Ptr<CvFileStorage> fs; //!< the underlying C FileStorage structure
string elname; //!< the currently written element
vector<char> structs; //!< the stack of written structures
int state; //!< the writer state
};

从XML或YAML文件中读取数据,可采用以下步骤:

1、利用构造函数 FileStorage::FileStorage()或方法 FileStorage::open()打开文件,这个过程包含解析文件,并将文件节点和数据存入内存中。

2、读取节点数据。利用下标操作符 FileStorage::operator []()FileNode::operator []()或 FileNodeIterator。

3、调用 FileStorage::release() 关闭文件。

OpenCV利用 FileNode 存储XML或YAML文件中的每个节点,并用于读写。FileNode在 core.hpp 文件中定义如下:

class CV_EXPORTS_W_SIMPLE FileNode
{
public:
//! type of the file storage node
enum
{
NONE=, //!< empty node
INT=, //!< an integer
REAL=, //!< floating-point number
FLOAT=REAL, //!< synonym or REAL
STR=, //!< text string in UTF-8 encoding
STRING=STR, //!< synonym for STR
REF=, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others
SEQ=, //!< sequence
MAP=, //!< mapping
TYPE_MASK=,
FLOW=, //!< compact representation of a sequence or mapping. Used only by YAML writer
USER=, //!< a registered object (e.g. a matrix)
EMPTY=, //!< empty structure (sequence or mapping)
NAMED= //!< the node has a name (i.e. it is element of a mapping)
};
//! the default constructor
CV_WRAP FileNode();
//! the full constructor wrapping CvFileNode structure.
FileNode(const CvFileStorage* fs, const CvFileNode* node);
//! the copy constructor
FileNode(const FileNode& node);
//! returns element of a mapping node
FileNode operator[](const string& nodename) const;
//! returns element of a mapping node
CV_WRAP FileNode operator[](const char* nodename) const;
//! returns element of a sequence node
CV_WRAP FileNode operator[](int i) const;
//! returns type of the node
CV_WRAP int type() const; //! returns true if the node is empty
CV_WRAP bool empty() const;
//! returns true if the node is a "none" object
CV_WRAP bool isNone() const;
//! returns true if the node is a sequence
CV_WRAP bool isSeq() const;
//! returns true if the node is a mapping
CV_WRAP bool isMap() const;
//! returns true if the node is an integer
CV_WRAP bool isInt() const;
//! returns true if the node is a floating-point number
CV_WRAP bool isReal() const;
//! returns true if the node is a text string
CV_WRAP bool isString() const;
//! returns true if the node has a name
CV_WRAP bool isNamed() const;
//! returns the node name or an empty string if the node is nameless
CV_WRAP string name() const;
//! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise.
CV_WRAP size_t size() const;
//! returns the node content as an integer. If the node stores floating-point number, it is rounded.
operator int() const;
//! returns the node content as float
operator float() const;
//! returns the node content as double
operator double() const;
//! returns the node content as text string
operator string() const; //! returns pointer to the underlying file node
CvFileNode* operator *();
//! returns pointer to the underlying file node
const CvFileNode* operator* () const; //! returns iterator pointing to the first node element
FileNodeIterator begin() const;
//! returns iterator pointing to the element following the last node element
FileNodeIterator end() const; //! reads node elements to the buffer with the specified format
void readRaw( const string& fmt, uchar* vec, size_t len ) const;
//! reads the registered object and returns pointer to it
void* readObj() const; // do not use wrapper pointer classes for better efficiency
const CvFileStorage* fs;
const CvFileNode* node;
};

写XML、YAML文件时主要注意的几点:

1、XML和YAML可以嵌套的两种集合类型:映射(mappings)、序列(sequences)。映射集合类似STL中的std::map和Python中的字典,序列集合类似STL中std::vector和 Python的序列;

2、当写入映射结构的数据时,节点的值(value)紧跟着节点的键(key);当写入序列结构的数据时,一个一个写入即可;

3、写入映射结构数据时,格式如下:fs << "{" << element_key << element_value << "}"

4、写入序列结构数据时,格式如下:fs << "[" << element_value << …… << "]"

5、写入映射、序列嵌套的数据时,以"{:"代替"{","[:" 代替 "["。

示例代码如下:

#include <QtCore/QCoreApplication>
#include <opencv2/core/core.hpp>
#include <time.h>
#include <iostream> void writeYAML()
{
cv::FileStorage fs("../file/test.yml", cv::FileStorage::WRITE); fs << "frameCount" << ;
time_t rawtime;
time(&rawtime); fs << "calibrationDate" << asctime(localtime(&rawtime)); cv::Mat cameraMatrix = (cv::Mat_<double>(,) << ,,,,,,,,);
cv::Mat distCoeffs = (cv::Mat_<double>(,) << 0.1, 0.01, -0.001, , );
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
fs << "features" << "[";
for(int i=; i < ; i++)
{
int x = rand() % ;
int y = rand() % ;
unsigned char lbp = rand() % ; fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
for(int j=; j < ; j++)
fs << ((lbp >> j) & );
fs << "]" << "}";
}
fs << "]";
fs.release();
} void readYAML()
{
cv::FileStorage fs2("../file/test.yml",cv::FileStorage::READ); int frameCount = (int)fs2["frameCount"];
std::string date;
fs2["calibrationDate"] >> date; cv::Mat cameraMatrix2, distCoeffs2;
fs2["cameraMatrix"] >> cameraMatrix2;
fs2["distCoeffs"] >> distCoeffs2; std::cout << "frameCount: " << frameCount << std::endl;
std::cout << "calibration date: " << date << std::endl;
std::cout << "camera matrix: " << cameraMatrix2 << std::endl;
std::cout << "distortion coeffs: " << distCoeffs2 << std::endl; cv::FileNode features = fs2["features"];
cv::FileNodeIterator it = features.begin(), it_end = features.end();
int idx = ;
std::vector<unsigned char> lbpval; for(; it != it_end; ++it, idx++)
{
std::cout << "features #" << idx << ": ";
std::cout << "x=" << (int)(*it)["x"] << ", y=" <<
(int)(*it)["y"] << ", lbp: ("; (*it)["lbp"] >> lbpval;
for(int i = ; i < (int)lbpval.size(); i++)
std::cout << " " << (int)lbpval[i];
std::cout << ")" << std::endl;
}
fs2.release();
} int main(int argc, char *argv[])
{
// QCoreApplication a(argc, argv);
// return a.exec(); // writeYAML();
readYAML(); return ;
}

写入的YAML文件如下:

读取YAML文件输出如下:

OpenCV持久化(一)的更多相关文章

  1. OpenCV持久化(二)

    如何利用OpenCV持久化自己的数据结构?我们来看看OpenCV中的一个例子. MyData.hpp定义自己的数据结构MyData如下: #ifndef MYDATA_HPP #define MYDA ...

  2. OpenCV基础知识介绍

    1.图像与矩阵 一般来说,图像是一个标准的矩形,有着宽度(width)和高度(height).而矩阵有着行(row)和列(column),矩阵的操作在数学和计算机中的处理都很常见且成熟,于是很自然的就 ...

  3. opencv学习笔记——FileStorage类的数据存取操作

    OpenCV的许多应用都需要使用数据的存储于读取,例如经过3D校准后的相机,需要存储校准结果矩阵,以方便下次调用该数据:基于机器学习的应用,同样需要将学习得到的参数保存等.OpenCV通过XML/YA ...

  4. 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑

    阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...

  5. opencv在图像显示中文

    在图像定位和模式识别时,经常需要把结果标注到图片上,标注内容可以是数字字母.矩形框等(opencv支持的)或者是中文汉字(借助freetype). 1.显示数字/矩形框 #include <op ...

  6. opencv中Mat与IplImage,CVMat类型之间转换

    opencv中对图像的处理是最基本的操作,一般的图像类型为IplImage类型,但是当我们对图像进行处理的时候,多数都是对像素矩阵进行处理,所以这三个类型之间的转换会对我们的工作带来便利. Mat类型 ...

  7. opencv源码:cascadedetect

    级联分类器检测类CascadeClassifier,提供了两个重要的方法: CascadeClassifier cascade_classifier; cascade_classifier.load( ...

  8. 基于OpenCV的车辆检测与追踪的实现

    最近老师布置了一个作业,是做一个基于视频的车辆检测与追踪,用了大概两周的时间做了一个简单的,效果不是很理想,但抑制不住想把自己的一些认识写下来,这里就把一些网络上的博客整理一下分享给大家,希望帮助到大 ...

  9. SQL Server-聚焦计算列或计算列持久化查询性能(二十二)

    前言 上一节我们详细讲解了计算列以及计算列持久化的问题,本节我们依然如前面讲解来看看二者查询性能问题,简短的内容,深入的理解,Always to review the basics. 持久化计算列比非 ...

随机推荐

  1. 「Vue」实用组件

    一.时间格式 1.安装Moment模块 npm i moment -S2.main.js中设置全局过滤器 import moment from 'moment' Vue.filter('ctime', ...

  2. [Web] Web请求过程之二:DNS 域名解析

    一.域名解析过程 1.浏览器检查缓存,域名缓存时间可以通过 TTL 属性来设置. 2.如果浏览器缓存中没有,浏览器会去查找操作系统缓存中是否有这个域名对应的 DNS 解析结果.如果要设置域名对应的 I ...

  3. Java上传文件夹(Jersey)

    背景介绍:公司要在CMS系统上为运营人员提供一个功能供运营人员将做好的活动页面上传到阿里云存储上,上传的内容为一个文件夹,文件夹内部有.html网页,JS文件夹下有JS文件,CSS文件夹下有样式表,I ...

  4. Linux清屏命令

    1:clear 2:Ctrl+L 3:printf "\033c" 4:ALT+F8 By KillerLegend Ref:http://www.coolcoder.in/201 ...

  5. MapReduce (hive表SequenceFile的结果做输入)、MultipleOutputs和Reduce端迭代iterable的一些说明

    很长时间以来一直写hive,嵌套脚本.偶尔写UDF.  最近用Hive的dynamic partition和多路插入做一些事情,很遗憾的结果是非常不稳定,有时能成功,有时失败.(可能是因为hive版本 ...

  6. dup()&dup2()

    [dup()&dup2()] 都是复制文件描述符指针.dup2可以指定复制到哪一个新索引. 参考:http://hi.baidu.com/flikecn/item/e82e14bef06e8a ...

  7. vbs 解析 html 文档

    关于VBS采集,网上流行比较多的方法都是正则,其实 htmlfile 可以解析 html 代码,但如果 designMode 没开启的话,有时候会包安全提示信息.但是开启 designMode (@预 ...

  8. [php]php总结(2)

    18.数组$arr[null] = 20; //array([]=>20)$arr[] = 20;//默认为下一个下标赋值unset()可以删除数组元素,但不会重建索引array_values( ...

  9. R8—批量生成文件夹,批量读取文件夹名称+R文件管理系统操作函数

    一. 批量生成文件夹,批量读取文件夹名称 今日,工作中遇到这样一个问题:boss给我们提供了200多家公司的ID代码(如6007.7920等),需要根据这些ID号去搜索下载新闻,从而将下载到的新闻存到 ...

  10. js数组排序 reverse()和sort()方法的使用

    WEB前端|js数组排序reverse()和sort()方法的使用,数组中已经存在两个可以直接用来重排序的方法:reverse()和sort(). reverse()方法会对反转数组项的顺序. var ...