加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 22:36:36 所属栏目:百科 来源:网络整理
导读:使用OpenCV,我们经常需要对xml文件进行操作。为此OpenCV为我们提供了FileStorage类来对XML/YAML文件进行操作。它使我们能够像操作普通文件一下来读写xml文件。 XML文件的打开和关闭 我们可以使用FileStorage的构造函数或者open()函数来对磁盘上的文件进行绑

使用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 <opencv2corecore.hpp>
#include <opencv2highguihighgui.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文件内容如下:

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读