• 利用opencv的FileStorage类实现XML/YAML文件的读写


      FileStorage是opencv2.0以后专门用来读写XML/YAML文件的类,标准的C++实现。利用好XML文件可以极大地方便我们对中间数据的处理。

    官方文档:

    (1) http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.html#fileinputoutputxmlyaml

    (2) http://docs.opencv.org/modules/core/doc/xml_yaml_persistence.html#filestorage

      利用FileStorage主要可以完成对以下几种数据的的输入和输出:数字、文本(字符串)、数组(vector)、maps、自定义数据类型(类)。与C++标准输入输出流的操作方法基本一致: 建立流对象-->打开文件(建立流与文件的连接)-->进行读或写操作-->关闭文件(断开流与文件的连接)。

      使用过程中需要注意以下几点:

      (1)打开文件的时候要指定是"WRITE"还是"READ",一旦指定就只能读或写。写完了要读或者读完了要写前,要先对流对象进行重定向(可以使用FileStorage::open()方法);

      (2)读写可以使用重载的<<和>>操作符,与C++风格保持了一致;

      (3)FileStorage的[]操作符返回一个FileNode数据类型,如果该节点是序列化的(vector),可以使用FileNodeIterator来迭代遍历该节点所有元素;

      (4)每次将FileStorage对象重定向到"WRITE"后,都会从头开始写,即会覆盖之前的全部内容;

      (5)读写自定义的数据类型(自定义类)时,要分别添加内部和外部的读写函数,外部的读写函数相当于对FileStorage对象的插入“<<”和提取“>>”运算符的重载,它们又调用了自定义类的内部读写函数,完成对数据成员的读写。

    以下是我的实验代码:

    #include <opencv2/core/core.hpp>
    #include <iostream>
    #include <string>
    
    using namespace std;
    using namespace cv;
    
    class MyData    //用户自定义类
    {
    public:
        MyData() : A(0), X(0), id() {}
        MyData(int i) : X(0), id()
        {
            A = i;
        }
    public:
        int A;
        double X;
        string id;
    public:
        //添加内部读写函数
        void write(FileStorage& fs) const
        {
            fs << "{" ;
            fs << "A" << A ;
            fs << "X" << X ;
            fs << "id" << id;
            fs << "}";
        }
        void read(const FileNode& node)
        {
            A = (int)(node["A"]);
            X = (double)(node["X"]);
            id = (string)(node["id"]);
            /*node["A"] >> A;
            node["X"] >> X;
            node["id"] >> id;*/
        }
    };
    
    //添加外部读写函数
    void write(FileStorage& fs, const std::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);
    }
    //重载<<操作符用于向标准输出流输出自定义类
    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 argc, char* argv[])
    {
        //打开XML文件
        string filename = "I.xml";
        //------------(1)------------
        FileStorage fs(filename, FileStorage::WRITE);
        //------------(2)------------
        //fs.open(filename, FileStorage::READ);
    
        //----------------简单数据结构输入输出----------------
        //输出数字和文本
        fs << "iterationNr" << 100;
        //输入数字和文本
        //fs.open(filename, FileStorage::READ);    //不要忘记将fs重定向为"READ"
        //int itNr;
        //------------(1)------------
        //fs["iterationNr"] >> itNr;
        //------------(2)------------
        //itNr = (int)fs["iterationNr"];
        //cout<<"iterationNr  "<<itNr;
        
        //输出大型数据结构Mat
        Mat R = Mat_<uchar >::eye  (3, 3),
            T = Mat_<double>::zeros(3, 1);
        fs << "R" << R;
        fs << "T" << T;
        //输入Mat
        //fs.open(filename, FileStorage::READ);    //不要忘记将fs重定向为"READ"
        //fs["R"] >> R;
        //fs["T"] >> T;
        //----------------------------------------------------------
    
        //----------------复杂数据结构输入输出----------------
        //输出数组(vector)
        fs<<"strings";
        fs<<"[";
        fs<<"image1.jpg"<<"Awesomeness"<<"baboon.jpg";
        fs<<"]";
        //输出maps
        fs<<"Mapping";
        fs<<"{";
        fs<<"One"<<1;
        fs<<"Two"<<2;
        fs<<"}";
    
        //输入数组
        //fs.open(filename, FileStorage::READ);    //不要忘记将fs重定向为"READ"
        //FileNode n = fs["strings"];    // 读取字符串序列 - 获取节点
        //if (n.type() != FileNode::SEQ)
        //{
        //    cerr << "strings is not a sequence! FAIL" << endl;
        //    return 1;
        //}
        //FileNodeIterator it = n.begin(), it_end = n.end(); // 遍历节点
        //for (; it != it_end; ++it)
        //    cout << (string)*it << endl;
        ////输入maps
        //n = fs["Mapping"];    // 从序列中读取map
        //cout << "Two  " << (int)(n["Two"]) << endl;
        //cout << "One  " << (int)(n["One"]) << endl;
        //----------------------------------------------------------
    
        //----------------自定义类输入输出----------------
        MyData m(1);
        //向文件输出
        fs << "MyData" << m;
        //由文件输入
        fs.open(filename, FileStorage::READ);    //不要忘记将fs重定向为"READ"
        fs["MyData"] >> m;
        fs["NonExisting"] >> m;   // 请注意不是 fs << "NonExisting" << m
        cout << endl << "NonExisting = " << endl << m << endl;
        //----------------------------------------------------------
    
        //关闭XML文件
        fs.release();
    
        return 0;
    }
  • 相关阅读:
    spring cloud项目搭建
    获取iframe的window对象
    数学杂谈 #7
    [AGC023D] Go Home
    JOISC 2021 部分题解
    [NOI2017]泳池
    [NOI2016] 循环之美
    [NOI2016] 优秀的拆分
    [LG P3676]小清新数据结构题
    [ARC113F]Social Distance
  • 原文地址:https://www.cnblogs.com/marcworld/p/3744747.html
Copyright © 2020-2023  润新知