opencv 2.x学习笔记十一读写xml文件

使用OpenCV,我们经常需要对xml文件进行操作。为此OpenCV为我们提供了FileStorage类来对XML/YAML文件进行操作。它使我们能够像操作普通文件一下来读写xml文件。

XML文件的打开和关闭

我们可以使用FileStorage的构造函数或者open()函数来对磁盘上的文件进行绑定。

	string filename = "test.xml";
	FileStorage fs( filename,FileStorage::WRITE );

	fs.open( filename,FileStorage::READ );

文件的扩展名决定了采用的输出格式,第二个参数指定了要对文件进行操作的类型。

我们可以通过isOpened函数来判断是否正确打开文件。

	if( !fs.isOpened() )
	{
		cerr << "filed to open!" << endl;
		return 1;
	}

我们可以显示的调用release函数来进行文件的关闭。也可以不调用,当FileStorage对象被销毁时,文件将自动被关闭。

	fs.release();

基本数据类型的输入/输出

我们可以使用<<操作符来简单的将基本数据类型的值写入文件。

	fs << "NUM" << 100;

我们还可以通过[]操作符和>>操作符来实现简单的读取。
	int num;
	num = (int) fs["NUM"];
	cout << num << endl;

OpenCV数据结构的输入/输出

它的操作方法和基本数据类型的操作方法是相同的。

<pre name="code" class="cpp">	Mat R = Mat_<uchar>::eye( 3,3 ),T = Mat_<double>::zeros( 3,1 );

	fs << "R" << R;
	fs<< "T" << T;

	Mat R1,T1;
	fs["R"] >> R1;
	fs["T"] >> T1;
 
 


vectors和maps的输入/输出

我们也可以对vectors(序列)和maps进行输入/输出

对于序列,在第一个元素前输出“[”,在最后一个元素后输出"]":

	// 序列
	fs << "strings" << "[";
	fs << "Hello" << "OpenCV" <<"!";
	fs << "]";

对于序列的读取,我们使用FileNode和FileNodeIterator数据结构。FileStorage的[]操作符将返回一个FileNode数据类型。我们一般使用FileNodeIterator来迭代遍历序列化的值。

	FileNode n = fs["strings"];
	if( n.type() != FileNode::SEQ )
	{
		cerr << "strings is not a sequence!" << endl;
		return 1;
	}
	FileNodeIterator it = n.begin(),it_end = n.end();
	for(; it != it_end; ++ it )
		cout << (string)*it << endl;

对于maps,输出采用同样的方法,但是采用“{”和"}"而不再是“[”和"]"。
	// map
	fs << "Mapping";
	fs << "{" << "One" << 1;
	fs << "Two" << 2 << "}";

对于maps的读取,我们使用FileNode数据结构和[]操作符来访问指定的元素。
	n = fs["Mapping"];
	if( n.type() != FileNode::MAP )
	{
		cerr << "strings is not a map!" << endl;
		return 1;
	}
	cout << "Two " << (int)(n["Two"]) << endl;
	cout << "One " << (int)(n["One"]) << endl;

读写自定义的数据结构

读写自定义的数据结构比较麻烦,我们为了使OpenCV的I/O接口能够像OpenCV内部结构一样对其进行序列化。我们需要重写read和write函数。

加入我们有如下的数据类型

class MyData
{
public:
      MyData() : A(0),X(0),id() {}
public:   // 数据成员
   int A;
   double X;
   string id;
};

我们需要重写read和write函数,首先在函数内部定义如下:
	void write( FileStorage& fs ) const
	{
		fs << "{" << "A" << A << "X" << X << "id" << id << "}";
	}
	void read( const FileNode& node )
	{
		A = (int)node["A"];
		X = (double)node["X"];
		id = (string)node["id"];
	}

然后还需要在类的外部进行如下定义:
void write( FileStorage& fs,const string&,const MyData& x )
{
	x.write(fs);
}
void read( const FileNode& node,MyData& x,const MyData& default_value = MyData() )
{
	if( node.empty() ) /* 定义了如果节点不存在的情况下的默认输出值 */
		x = default_value;
	else
		x.read( node );
}
为了能够使用<<操作符进行对自定数据结构进行操作,还需要对<<操作符进行重载,如下所示:
ostream& operator<<(ostream& out,const MyData& m)
{
    out << "{ A = " << m.A << ",";
    out << "X = " << m.X << ",";
    out << "id = " << m.id << "}";
    return out;
}
之后,我们就可以对自定义数据类型进行输入/输出。
	MyData m(1,3.14,"xml file");
	fs << "MyData" << m;

	MyData m1,m2;
	fs["MyData"] >> m1;
	/* 文件中没有m2的节点 */
	fs["m2"] >> m2;
	cout << "MyData m1 = " << endl << m1 << endl ;
	cout << "MyData m2 = " << endl << m2 << endl << endl;

完整示例

#include <opencv2\core\core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <iostream>
#include <string>

using namespace std;
using namespace cv;

class MyData
{
public:
	MyData():A(0),id(){}
	MyData(int a,double b,string c)
	{
		A = a;
		X = b;
		id = c;
	}
	void write( FileStorage& fs ) const
	{
		fs << "{" << "A" << A << "X" << X << "id" << id << "}";
	}
	void read( const FileNode& node )
	{
		A = (int)node["A"];
		X = (double)node["X"];
		id = (string)node["id"];
	}
public:
	int A;
	double X;
	string id;
};

void write( FileStorage& fs,const MyData& default_value = MyData() )
{
	if( node.empty() ) /* 定义了如果节点不存在的情况下的默认输出值 */
		x = default_value;
	else
		x.read( node );
}
ostream& operator<<(ostream& out,";
    out << "id = " << m.id << "}";
    return out;
}
int main()
{
	string filename = "test.xml";
	Mat R = Mat_<uchar>::eye( 3,1 );
	MyData m(1,"xml file");
	// write
	FileStorage fs( filename,FileStorage::WRITE );
	if( !fs.isOpened() )
	{
		cerr << "filed to open!" << endl;
		return 1;
	}
	fs << "NUM" << 100;

	// 序列
	fs << "strings" << "[";
	fs << "Hello" << "OpenCV" <<"!";
	fs << "]";

	// map
	fs << "Mapping";
	fs << "{" << "One" << 1;
	fs << "Two" << 2 << "}";

	fs << "R" << R;
	fs<< "T" << T;

	fs << "MyData" << m;
	cout << "Write Done!" << endl;

	// read
	cout << endl << "Reading: " << endl;
	fs.open( filename,FileStorage::READ );

	int num;
	num = (int) fs["NUM"];
	cout << num << endl;
	
	FileNode n = fs["strings"];
	if( n.type() != FileNode::SEQ )
	{
		cerr << "strings is not a sequence!" << endl;
		return 1;
	}
	FileNodeIterator it = n.begin(),it_end = n.end();
	for(; it != it_end; ++ it )
		cout << (string)*it << endl;

	n = fs["Mapping"];
	if( n.type() != FileNode::MAP )
	{
		cerr << "strings is not a map!" << endl;
		return 1;
	}
	cout << "Two " << (int)(n["Two"]) << endl;
	cout << "One " << (int)(n["One"]) << endl;

	Mat R1,T1;
	fs["R"] >> R1;
	fs["T"] >> T1;
	
	cout << endl
		<< "R = " << R1 << endl;
	cout << "T = " << T1 << endl << endl;

	MyData m1,m2;
	fs["MyData"] >> m1;
	/* 文件中没有m2的节点 */
	fs["m2"] >> m2;
	cout << "MyData m1 = " << endl << m1 << endl ;
	cout << "MyData m2 = " << endl << m2 << endl << endl;
	fs.release();
 	return 0;
}

运行结果:

得到的xml文件内容如下:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


php输出xml格式字符串
J2ME Mobile 3D入门教程系列文章之一
XML轻松学习手册
XML入门的常见问题(一)
XML入门的常见问题(三)
XML轻松学习手册(2)XML概念
xml文件介绍及使用
xml编程(一)-xml语法
XML文件结构和基本语法
第2章 包装类
XML入门的常见问题(二)
Java对象的强、软、弱和虚引用
JS解析XML文件和XML字符串详解
java中枚举的详细使用介绍
了解Xml格式
XML入门的常见问题(四)
深入SQLite多线程的使用总结详解
PlayFramework完整实现一个APP(一)
XML和YAML的使用方法
XML轻松学习总节篇