OpenCV 输入输出XML和YAML文件

OpenCV的学习中,经常会用到文件的输入输出,特别是XML和YAML格式的输出文件,如果大家有做过人脸识别就可以体会到,用主分量分析法得到的特征脸、平均脸等等数据都会被保存成为XML格式,方便下次使用时调用,OpenCV2版本比OpenCV1版本省去了很多函数,大家通过OpenCV中文网就可以查到,而且OpenCV2版本的输入输出使用与STL相同的 <</>> 输入/输出操作符,实现起来非常简单,在学习的过程中要特别注意,输入输出是map数据结构还是sequence数据结构,这两种结构上的操作会有所不同,现在我们就看看范例吧。

1、代码实现

[cpp]  view plain  copy
  1. #include "stdafx.h"  
  2.   
  3.   
  4. #include <opencv2/core/core.hpp>  
  5. #include <iostream>  
  6. #include <string>  
  7.   
  8. using namespace cv;  
  9. using namespace std;  
  10.   
  11. static void help()  
  12. {  
  13.     cout << endl  
  14.         <<" shows the usage of the OpenCV serialization functionality."         << endl  
  15.         << "usage: "                                                                      << endl  
  16.         <<  " outputfile.yml.gz"                                                 << endl  
  17.         << "The output file may be either XML (xml) or YAML (yml/yaml). You can even compress it by "  
  18.         << "specifying this in its extension like xml.gz yaml.gz etc... "                  << endl  
  19.         << "With FileStorage you can serialize objects in OpenCV by using the << and >> operators" << endl  
  20.         << "For example: - create a class and have it serialized"                         << endl  
  21.         << "             - use it to read and write matrices."                            << endl;  
  22. }  
  23.   
  24. class MyData  
  25. {  
  26. public:  
  27.     MyData() : A(0), X(0), id()  
  28.     {}  
  29.     explicit MyData(int) : A(97), X(CV_PI), id("mydata1234"// explicit to avoid implicit conversion  
  30.     {}  
  31.     void write(FileStorage& fs) const                        //Write serialization for this class  
  32.     {  
  33.         fs << "{" << "A" << A << "X" << X << "id" << id << "}";  
  34.     }  
  35.     void read(const FileNode& node)                          //Read serialization for this class  
  36.     {  
  37.         A = (int)node["A"];  
  38.         X = (double)node["X"];  
  39.         id = (string)node["id"];  
  40.     }  
  41. public:   // Data Members  
  42.     int A;  
  43.     double X;  
  44.     string id;  
  45. };  
  46.   
  47. //These write and read functions must be defined for the serialization in FileStorage to work  
  48. static void write(FileStorage& fs, const std::string&, const MyData& x)  
  49. {  
  50.     x.write(fs);  
  51. }  
  52. static void read(const FileNode& node, MyData& x, const MyData& default_value = MyData()){  
  53.     if(node.empty())  
  54.         x = default_value;  
  55.     else  
  56.         x.read(node);  
  57. }  
  58.   
  59. // This function will print our custom class to the console  
  60. static ostream& operator<<(ostream& out, const MyData& m)  
  61. {  
  62.     out << "{ id = " << m.id << ", ";  
  63.     out << "X = " << m.X << ", ";  
  64.     out << "A = " << m.A << "}";  
  65.     return out;  
  66. }  
  67.   
  68. int main(int ac, char** av)  
  69. {  
  70.   
  71.     string filename = "F:\\OpenCV2.4.8\\file_input_output\\file_input_output\\input_output.xml";  
  72.     { //write  
  73.         Mat R = Mat_<uchar>::eye(3, 3),  
  74.             T = Mat_<double>::zeros(3, 1);  
  75.         MyData m(1);  
  76.   
  77.         FileStorage fs(filename, FileStorage::WRITE);  
  78.   
  79.         fs << "iterationNr" << 100;  
  80.         fs << "strings" << "[";                              // text - string sequence  
  81.         fs << "image1.jpg" << "Awesomeness" << "baboon.jpg";  
  82.         fs << "]";                                           // close sequence  
  83.   
  84.         fs << "Mapping";                              // text - mapping  
  85.         fs << "{" << "One" << 1;  
  86.         fs <<        "Two" << 2 << "}";  
  87.   
  88.         fs << "R" << R;                                      // cv::Mat  
  89.         fs << "T" << T;  
  90.   
  91.         fs << "MyData" << m;                                // your own data structures  
  92.   
  93.         fs.release();                                       // explicit close  
  94.         cout << "Write Done." << endl;  
  95.     }  
  96.   
  97.     {//read  
  98.         cout << endl << "Reading: " << endl;  
  99.         FileStorage fs;  
  100.         fs.open(filename, FileStorage::READ);  
  101.   
  102.         int itNr;  
  103.         //fs["iterationNr"] >> itNr;  
  104.         itNr = (int) fs["iterationNr"];  
  105.         cout << itNr;  
  106.         if (!fs.isOpened())  
  107.         {  
  108.             cerr << "Failed to open " << filename << endl;  
  109.             help();  
  110.             return 1;  
  111.         }  
  112.   
  113.         FileNode n = fs["strings"];                         // Read string sequence - Get node  
  114.         if (n.type() != FileNode::SEQ)  
  115.         {  
  116.             cerr << "strings is not a sequence! FAIL" << endl;  
  117.             return 1;  
  118.         }  
  119.   
  120.         FileNodeIterator it = n.begin(), it_end = n.end(); // Go through the node  
  121.         for (; it != it_end; ++it)  
  122.             cout << (string)*it << endl;  
  123.   
  124.   
  125.         n = fs["Mapping"];                                // Read mappings from a sequence  
  126.         cout << "Two  " << (int)(n["Two"]) << "; ";  
  127.         cout << "One  " << (int)(n["One"]) << endl << endl;  
  128.   
  129.   
  130.         MyData m;  
  131.         Mat R, T;  
  132.   
  133.         fs["R"] >> R;                                      // Read cv::Mat  
  134.         fs["T"] >> T;  
  135.         fs["MyData"] >> m;                                 // Read your own structure_  
  136.   
  137.         cout << endl  
  138.             << "R = " << R << endl;  
  139.         cout << "T = " << T << endl << endl;  
  140.         cout << "MyData = " << endl << m << endl << endl;  
  141.   
  142.         //Show default behavior for non existing nodes  
  143.         cout << "Attempt to read NonExisting (should initialize the data structure with its default).";  
  144.         fs["NonExisting"] >> m;  
  145.         cout << endl << "NonExisting = " << endl << m << endl;  
  146.     }  
  147.   
  148.     cout << endl  
  149.         << "Tip: Open up " << filename << " with a text editor to see the serialized data." << endl;  
  150.     char ch=NULL;  
  151.     while (ch!='c')  
  152.     {  
  153.         cin>>ch;  
  154.     }  
  155.     return 0;  
  156. }  

2、运行结果


                           图1、运行结果


                    图2、文件格式 

3、总结

范例很简单,大家看看就可以明白了,这里强调的两点是:

①、输入输出是sequence还是map

sequence:输入操作:在第一个元素前输出“[”字符,并在最后一个元素后输出“]”字符。如:

[cpp]  view plain  copy
  1. fs << "strings" << "[";                              // 文本 - 字符串序列  
  2. fs << "image1.jpg" << "Awesomeness" << "baboon.jpg";  
  3. fs << "]";                                           // 序列结束  
           输出操作: 可使用  FileNode  和  FileNodeIterator  数据结构。  FileStorage  的[] 操作符将返回一个  FileNode  数据类型。如果这个节点是序列化的,我们可以使用  FileNodeIterator  来迭代遍历所有元素。如:

[cpp]  view plain  copy
  1. FileNode n = fs["strings"];                         // 读取字符串序列 - 获取节点  
  2. if (n.type() != FileNode::SEQ)  
  3. {  
  4.     cerr << "strings is not a sequence! FAIL" << endl;  
  5.     return 1;  
  6. }  
  7.   
  8. FileNodeIterator it = n.begin(), it_end = n.end(); // 遍历节点  
  9. for (; it != it_end; ++it)  
  10.     cout << (string)*it << endl;  
map: 输入操作: 采用”{“和”}“作为分隔符。如:

[cpp]  view plain  copy
  1. fs << "Mapping";                              // 文本 - mapping  
  2. fs << "{" << "One" << 1;  
  3. fs <<        "Two" << 2 << "}";  
     输出操作: 可以用 [] 操作符访问指定的元素(或者 >> 操作符)。如:

[cpp]  view plain  copy
  1. n = fs["Mapping"];                                // 从序列中读取map  
  2. cout << "Two  " << (int)(n["Two"]) << "; ";  
  3. cout << "One  " << (int)(n["One"]) << endl << endl;  

②、读写自定义类型

  读写自定义类型时,需要自己写内部和外部的读写函数,学完后就可以使用OpenCV I/O XML/YAML接口对其进行序列化(就像对OpenCV数据结构进行序列化一样)。

4、用到的类和函数

FileStorage:

功能:文件存储结构

当OpenCV想打开或保存文件时,可以使用FileStorage的构造函数,或者用open()函数

[cpp]  view plain  copy
  1. string filename = "I.xml";  
  2. FileStorage fs(filename, FileStorage::WRITE);  
  3. \\...  
  4. fs.open(filename, FileStorage::READ);  
无论以哪种方式绑定,函数中的第二个参数都以常量形式指定你要对文件进行操作的类型,包括:WRITE, READ 或 APPEND。文件扩展名决定了你将采用的输出格式。如果你指定扩展名如  .xml.gz  ,输出甚至可以是压缩文件。

当 FileStorage对象被销毁时,文件将自动关闭。当然你也可以显示调用 release 函数:

[cpp]  view plain  copy
  1. fs.release();  

FileNode:

功能:体现了文件存储的每一个元素。

FileStorage 的[] 操作符将返回一个 FileNode 数据类型,它可以是一个矩阵、数据、头结点等等,包含了所有的文件内容,而文件节点的类型可以通过 FileNode::type()方法获得。

FileNodeIterator:

功能:文件迭代遍历

可以通过它迭代遍历所有元素,具体功能见前面代码,之前博客也有介绍过迭代遍历,功能、方法都差不多。


转自 chenjianzhou12的专栏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值