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 <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文件内容如下:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |