使用XML文件输入和输出和YAML文件 目标 你会发现以下问题的答案: 如何打印和阅读文本条目文件和OpenCV使用YAML或XML文件? 如何为OpenCV做同样的数据结构?

使用XML文件输入和输出和YAML文件

目标

你会发现以下问题的答案:

  • 如何打印和阅读文本条目文件和OpenCV使用YAML或XML文件?
  • 如何为OpenCV做同样的数据结构?
  • 为你的数据结构如何做到这一点?
  • 使用OpenCV的数据结构等FileStorage,FileNodeFileNodeIterator

源代码

你可以下载 在这里或找到它样品/ cpp / tutorial_code / / file_input_output / file_input_output.cpp核心OpenCV的源代码库。

下面是一个示例代码如何实现所有目标的东西枚举列表。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <opencv2/core/core.hpp>
#include <iostream>
#include <string>

using namespace cv;
using namespace std;

class MyData
{
public:
    MyData() : A(0), X(0), id()
    {}
    explicit MyData(int) : A(97), X(CV_PI), id("mydata1234") // explicit to avoid implicit conversion
    {}
    void write(FileStorage& fs) const                        //Write serialization for this class
    {
        fs << "{" << "A" << A << "X" << X << "id" << id << "}";
    }
    void read(const FileNode& node)                          //Read serialization for this class
    {
        A = (int)node["A"];
        X = (double)node["X"];
        id = (string)node["id"];
    }
public:   // Data Members
    int A;
    double X;
    string id;
};

//These write and read functions must be defined for the serialization in FileStorage to work
static void write(FileStorage& fs, const std::string&, const MyData& x)
{
    x.write(fs);
}
static void read(const FileNode& node, MyData& x, const MyData& default_value = MyData()){
    if(node.empty())
        x = default_value;
    else
        x.read(node);
}

// This function will print our custom class to the console
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 ac, char** av)
{
    if (ac != 2)
    {
        help(av);
        return 1;
    }

    string filename = av[1];
    { //write
        Mat R = Mat_<uchar>::eye(3, 3),
            T = Mat_<double>::zeros(3, 1);
        MyData m(1);

        FileStorage fs(filename, FileStorage::WRITE);

        fs << "iterationNr" << 100;
        fs << "strings" << "[";                              // text - string sequence
        fs << "image1.jpg" << "Awesomeness" << "baboon.jpg";
        fs << "]";                                           // close sequence

        fs << "Mapping";                              // text - mapping
        fs << "{" << "One" << 1;
        fs <<        "Two" << 2 << "}";

        fs << "R" << R;                                      // cv::Mat
        fs << "T" << T;

        fs << "MyData" << m;                                // your own data structures

        fs.release();                                       // explicit close
        cout << "Write Done." << endl;
    }

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

        int itNr;
        //fs["iterationNr"] >> itNr;
        itNr = (int) fs["iterationNr"];
        cout << itNr;
        if (!fs.isOpened())
        {
            cerr << "Failed to open " << filename << endl;
            help(av);
            return 1;
        }

        FileNode n = fs["strings"];                         // Read string sequence - Get node
        if (n.type() != FileNode::SEQ)
        {
            cerr << "strings is not a sequence! FAIL" << endl;
            return 1;
        }

        FileNodeIterator it = n.begin(), it_end = n.end(); // Go through the node
        for (; it != it_end; ++it)
            cout << (string)*it << endl;


        n = fs["Mapping"];                                // Read mappings from a sequence
        cout << "Two  " << (int)(n["Two"]) << "; ";
        cout << "One  " << (int)(n["One"]) << endl << endl;


        MyData m;
        Mat R, T;

        fs["R"] >> R;                                      // Read cv::Mat
        fs["T"] >> T;
        fs["MyData"] >> m;                                 // Read your own structure_

        cout << endl
            << "R = " << R << endl;
        cout << "T = " << T << endl << endl;
        cout << "MyData = " << endl << m << endl << endl;

        //Show default behavior for non existing nodes
        cout << "Attempt to read NonExisting (should initialize the data structure with its default).";
        fs["NonExisting"] >> m;
        cout << endl << "NonExisting = " << endl << m << endl;
    }

    cout << endl
        << "Tip: Open up " << filename << " with a text editor to see the serialized data." << endl;

    return 0;
}

解释

这里我们只讨论XML和YAML文件输入。 您的输出文件(及其各自的输入)可能只有其中一个扩展和来自这个结构。 他们是两种类型的数据结构可以序列化:映射STL(如地图)元素序列(如STL向量)。 之间的区别是,在地图上每个元素都有一个唯一的名称通过你可能访问它。 序列需要通过他们来查询一个特定的项目。

  1. XML / YAML文件打开和关闭。之前你写任何内容这样的文件你需要打开它,最后关闭它。 中的XML数据结构/ YAML OpenCVFileStorage。 指定这个结构,文件绑定在你的硬盘你可以使用它的构造函数或open()的函数:

    string filename = "I.xml";
    FileStorage fs(filename, FileStorage::WRITE);
    //...
    fs.open(filename, FileStorage::READ);
    

    任何一个使用第二个参数是一个常数的指定类型的操作你可以在他们:写,读或附加。 中指定的扩展文件名也将使用这种番茄的输出格式。 输出可能甚至压缩等如果您指定一个扩展.xml.gz

    文件时自动关闭FileStorage对象被摧毁。 然而,你可以通过显式地调用释放功能:

    fs.release();                                       // explicit close
    
  2. 输入和输出的文本和数字。数据结构使用相同的< <输出操作符STL库。 输出任何类型的数据结构,我们需要指定它的名字。 我们这样做只是打印的名字。 基本类型你可以参照这个打印的值:

    fs << "iterationNr" << 100;
    

    阅读是一个简单的解决(通过[]操作符)和铸造操作或读通过> >操作符:

    int itNr;
    fs["iterationNr"] >> itNr;
    itNr = (int) fs["iterationNr"];
    
  3. OpenCV的输入/输出数据结构。这些行为完全就像c++的基本类型:

    Mat R = Mat_<uchar >::eye  (3, 3),
        T = Mat_<double>::zeros(3, 1);
    
    fs << "R" << R;                                      // Write cv::Mat
    fs << "T" << T;
    
    fs["R"] >> R;                                      // Read cv::Mat
    fs["T"] >> T;
    
  4. 向量的输入/输出(数组)和关联映射。正如我之前提到的,我们可以输出地图和序列(数组、向量)。 我们首先打印变量的名称,然后我们必须指定如果我们的输出是一个序列或地图。

    序列的第一个元素之前打印“(”字符之后,最后一个“]”的角色:

    fs << "strings" << "[";                              // text - string sequence
    fs << "image1.jpg" << "Awesomeness" << "baboon.jpg";
    fs << "]";                                           // close sequence
    

    地图的钻是一样的但是现在我们使用“{”和“}”分隔符字符:

    fs << "Mapping";                              // text - mapping
    fs << "{" << "One" << 1;
    fs <<        "Two" << 2 << "}";
    

    从这些我们使用阅读FileNodeFileNodeIterator数据结构。 []的运营商FileStorage返回一个类FileNode数据类型。 如果我们可以使用的节点顺序FileNodeIterator遍历项目:

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

    地图你可以再次使用[]操作符访问给定的项目(或> >操作符):

    n = fs["Mapping"];                                // Read mappings from a sequence
    cout << "Two  " << (int)(n["Two"]) << "; ";
    cout << "One  " << (int)(n["One"]) << endl << endl;
    
  5. 阅读和编写自己的数据结构。假设您有一个数据结构,如:

    class MyData
    {
    public:
          MyData() : A(0), X(0), id() {}
    public:   // Data Members
       int A;
       double X;
       string id;
    };
    

    可以通过序列化XML / YAML OpenCV I / O接口(就像OpenCV数据结构的情况下)通过添加一个读和写函数类的内部和外部。 里面的部分:

    void write(FileStorage& fs) const                        //Write serialization for this class
    {
      fs << "{" << "A" << A << "X" << X << "id" << id << "}";
    }
    
    void read(const FileNode& node)                          //Read serialization for this class
    {
      A = (int)node["A"];
      X = (double)node["X"];
      id = (string)node["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);
    }
    

    在这里你可以观察到在阅读部分我们定义如果用户试图读取一个不存在的节点。 在这种情况下我们只是返回默认的初始化值,但是一个更详细的解决方案是换取实例-一个值对象的ID。

    一旦你添加这四个功能为编写和使用> >运算符< <操作符读:

    MyData m(1);
    fs << "MyData" << m;                                // your own data structures
    fs["MyData"] >> m;                                 // Read your own structure_
    

    或者尝试读一个不存在的阅读:

    fs["NonExisting"] >> m;   // Do not add a fs << "NonExisting" << m command for this to work
    cout << endl << "NonExisting = " << endl << m << endl;
    

结果

主要是我们刚刚打印出定义的数字。 你的控制台屏幕上可以看到:

Write Done.

Reading:
100image1.jpg
Awesomeness
baboon.jpg
Two  2; One  1


R = [1, 0, 0;
  0, 1, 0;
  0, 0, 1]
T = [0; 0; 0]

MyData =
{ id = mydata1234, X = 3.14159, A = 97}

Attempt to read NonExisting (should initialize the data structure with its default).
NonExisting =
{ id = , X = 0, A = 0}

Tip: Open up output.xml with a text editor to see the serialized data.

然而,更有趣的是你可以看到输出xml文件中:

<?xml version="1.0"?>
<opencv_storage>
<iterationNr>100</iterationNr>
<strings>
  image1.jpg Awesomeness baboon.jpg</strings>
<Mapping>
  <One>1</One>
  <Two>2</Two></Mapping>
<R type_id="opencv-matrix">
  <rows>3</rows>
  <cols>3</cols>
  <dt>u</dt>
  <data>
    1 0 0 0 1 0 0 0 1</data></R>
<T type_id="opencv-matrix">
  <rows>3</rows>
  <cols>1</cols>
  <dt>d</dt>
  <data>
    0. 0. 0.</data></T>
<MyData>
  <A>97</A>
  <X>3.1415926535897931e+000</X>
  <id>mydata1234</id></MyData>
</opencv_storage>

或者是YAML文件:

%YAML:1.0
iterationNr: 100
strings:
   - "image1.jpg"
   - Awesomeness
   - "baboon.jpg"
Mapping:
   One: 1
   Two: 2
R: !!opencv-matrix
   rows: 3
   cols: 3
   dt: u
   data: [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]
T: !!opencv-matrix
   rows: 3
   cols: 1
   dt: d
   data: [ 0., 0., 0. ]
MyData:
   A: 97
   X: 3.1415926535897931e+000
   id: mydata1234
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值