学习目标:
本文档将解决以下问题:
如何在OpenCV中利用XML和YAML读取和打印文件?
如何利用XML和YAML对OpenCV内建的数据结构读取和打印?
如何利用XML和YAML对用户自定义的数据结构打印?
学习使用OpenCV的相关数据结构,cv::FileStorage,cv::FileNode,cv::FileN
odeIterator。
源文件:
以下源文件可以在OpenCVd的官方网站上下载(其中的注释被改写为中文)。
#include<opencv2/core.hpp>
#include<iostream>
#include<string>
using namespace std;
using namespace cv;
static void help(char** av)
{
cout<<endl
<<av[0]<<"shows the usage of the OpenCV serialization functionality." <<endl
<<"Usage:"
<<av[0]<<"outputfile.yml.gz" <<endl
<<"The output file may be either XML or YAML(yml/yaml).You can even compress it "
<<"by specifying this in its extension like xml.gz yaml.gz etc..."
<<"With FileStorage you can serialize objects in OpenCV by using the << and >> operators"<<endl
<<"For example: -create a class and have it serialized" <<endl
<<" -use it to read and write matrices."<<endl;
// 以上是对程序的介绍,说明了可以对XML和YAML或者压缩文件打开,对自定义的类也可以使用,同时"<<"">>"
// 这两个操作符被重载
}
class myData
{
pubic:
MyData():A(0),X(0),id(0)
{}
explicit MyData(int):A(97),X(CV_PI),id("mydata1234")
{}
void write(FileStorage& fs) const // 向文件写入函数,将MyData的数据以map的形式写入文件
{ //"{"表示map,"["表示sequence.
fs<<"{"<<"A"<<A<<"X"<<X<<"id"<<id<<"}";
}
void read(const FileNode& node) // 读文件函数,将文件中特定的数据读入MyData的数据成员中
{
A = (int)node["A"];
X = (double)node["X"];
id = (string)node["id"];
}
public:
int A;
double X;
string id;
}; // end MyData
static void write(FileStorage& fs,const std::string& ,const MyData& x)
{
x.write(fs);
}
static void read(const FileNode& node,MyData& x,const MyData& default_value = MyData())
{
if(node.empty())
x = default_value;
else
x.read(node);
}
static ostream& operator<<(ostream& out,const MyData& m)
{
out<<"{ id = "<<m.id<<",";
out<<"X = "<<m.X<<",";
out<<"A = "<<m.A<<"}";
return out;
}
int main(int ac,char** av)
{
if(ac != 2)
{
help(av);
return 1;
}
string filename = av[1];
{
// write
Mat R = Mat_<uchar>::eye(3,3);
T = Mat_<double>::zeros(3,1);
MyData m(1);
FileStorage fs(filename,FileStorage::WRITE); // 将fs对象和文件关联起来,即打开一个文件。
fs<<"iterationNr"<<100;
fs<<"strings"<<"["; // 写一个字符序列,注意"["表示sequence
fs<<"image1.jpg"<<"Awesomeness"<<"../data/bacoon.jpg";
fs<<"]"; // 字符写完毕
fs<<"Mapping";
fs<<"R"<<R;
fs<<"T"<<T;
fs<<"MyData"<<m;
fs.reslease(); // 关闭fs打开的文件
cout<<"Write done."<<endl;
}
{// 读操作
cout<<endl<<"Reading: "<<endl;
FileStorage fs;
fs.open(filename,FileStorage::READ);
int itNr;
// fs["iterationNr"]>>itNr;
itNr = (int)fs["iterationNr"]; // 读取文件中的某一项并赋值给itNr,注意此处强制类型转换,和上面功能相同
cout<<itNr;
if(!fs.isOpened())
{
cerr<<"Failed to open "<<filename<<endl;
help(av);
return 1;
}
FileNode n = fs["strings"]; // 读取string 序列
if(n.type() != FileNode::SEQ) // 检查n是否是序列对象
{
cerr<<"strings is not a sequence! FAIL"<<endl;
return 1;
}
FileNodeIterator it = n.begin(),it_end = n.end(); // 和STL风格类似的迭代器
for(; it != it_end;it++)
{
cout<<(string)*it<<endl;
}
n = fs["Mapping"]; // 读取map结构
cout<<"Two "<<(int)(n["Two"])<<";";
cout<<"One "<<(int)(n["One"])<<endl<<endl;
MyData m;
Mat R,T;
fs["R"]>>R;
fs["T"]>>T;
fs["MyData"]>>m;
cout<<endl
<<"R = "<<R<<endl;
cout<<"T = "<<T<<endl;
cout<<"MyData = "<<m<<endl<<endl;
// 展示对不存在的节点的读取特性
cout<<"Attempt to reand NonExisting(should initialize the data structure with its default)."
fs["NonExisting"]>>m;
cout<<endl<<"NonExisting"<<m<<endl;
}
cout<<endl
<<"Tip: Open up "<<filename<<" with a text editor to see the serialized data."
return 0;
}