其他分享
首页 > 其他分享> > XML和YAML文件的输入和输出

XML和YAML文件的输入和输出

作者:互联网

1.目标

您将找到以下问题的答案:

2.源代码

下面是如何实现目标列表中列举的所有内容的示例代码。

2.1 C++代码

#include <opencv2/core.hpp>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
static void help(char** av)
{
    cout << endl
        << av[0] << " shows the usage of the OpenCV serialization functionality."         << endl
        << "usage: "                                                                      << endl
        <<  av[0] << " outputfile.yml.gz"                                                 << endl
        << "The output file may be either XML (xml) or YAML (yml/yaml). You can even compress it by "
        << "specifying this in its extension like xml.gz yaml.gz etc... "                  << endl
        << "With FileStorage you can serialize objects in OpenCV by using the << and >> operators" << endl
        << "For example: - create a class and have it serialized"                         << endl
        << "             - use it to read and write matrices."                            << endl;
}
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);
        // or:
        // FileStorage fs;
        // fs.open(filename, FileStorage::WRITE);
        fs << "iterationNr" << 100;
        fs << "strings" << "[";                              // text - string sequence
        fs << "image1.jpg" << "Awesomeness" << "../data/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;
}

2.2Python代码

from __future__ import print_function
import numpy as np
import cv2 as cv
import sys
def help(filename):
    print (
        '''
        {0} shows the usage of the OpenCV serialization functionality. \n\n
        usage:\n
            python3 {0} outputfile.yml.gz\n\n
        The output file may be either in XML, YAML or JSON. You can even compress it\n
        by specifying this in its extension like xml.gz yaml.gz etc... With\n
        FileStorage you can serialize objects in OpenCV.\n\n
        For example: - create a class and have it serialized\n
                     - use it to read and write matrices.\n
        '''.format(filename)
    )
class MyData:
    A = 97
    X = np.pi
    name = 'mydata1234'
    def __repr__(self):
        s = '{ name = ' + self.name + ', X = ' + str(self.X)
        s = s + ', A = ' +  str(self.A) + '}'
        return s
    
    def write(self, fs, name):
        fs.startWriteStruct(name, cv.FileNode_MAP|cv.FileNode_FLOW)
        fs.write('A', self.A)
        fs.write('X', self.X)
        fs.write('name', self.name)
        fs.endWriteStruct()
    def read(self, node):
        if (not node.empty()):
            self.A = int(node.getNode('A').real())
            self.X = node.getNode('X').real()
            self.name = node.getNode('name').string()
        else:
            self.A = self.X = 0
            self.name = ''
    
def main(argv):
    if len(argv) != 2:
        help(argv[0])
        exit(1)
    # write
    
    R = np.eye(3,3)
    T = np.zeros((3,1))
    
    m = MyData()
    
    filename = argv[1]
    
    s = cv.FileStorage(filename, cv.FileStorage_WRITE)
    # or:
    # s = cv.FileStorage()
    # s.open(filename, cv.FileStorage_WRITE)
    
    
    s.write('iterationNr', 100)
    
    
    s.startWriteStruct('strings', cv.FileNode_SEQ)
    for elem in ['image1.jpg', 'Awesomeness', '../data/baboon.jpg']:
        s.write('', elem)
    s.endWriteStruct()
    
    
    s.startWriteStruct('Mapping', cv.FileNode_MAP)
    s.write('One', 1)
    s.write('Two', 2)
    s.endWriteStruct()
    
    
    s.write('R_MAT', R)
    s.write('T_MAT', T)
    
    
    m.write(s, 'MyData')
    
    s.release()
    
    print ('Write Done.')
    # read
    print ('\nReading: ')
    s = cv.FileStorage()
    s.open(filename, cv.FileStorage_READ)
    
    n = s.getNode('iterationNr')
    itNr = int(n.real())
    
    print (itNr)
    if (not s.isOpened()):
        print ('Failed to open ', filename, file=sys.stderr)
        help(argv[0])
        exit(1)
    
    n = s.getNode('strings')
    if (not n.isSeq()):
        print ('strings is not a sequence! FAIL', file=sys.stderr)
        exit(1)
    for i in range(n.size()):
        print (n.at(i).string())
    
    
    n = s.getNode('Mapping')
    print ('Two',int(n.getNode('Two').real()),'; ')
    print ('One',int(n.getNode('One').real()),'\n')
    
    
    R = s.getNode('R_MAT').mat()
    T = s.getNode('T_MAT').mat()
    
    m.read(s.getNode('MyData'))
    
    print ('\nR =',R)
    print ('T =',T,'\n')
    print ('MyData =','\n',m,'\n')
    
    print ('Attempt to read NonExisting (should initialize the data structure',
            'with its default).')
    m.read(s.getNode('NonExisting'))
    print ('\nNonExisting =','\n',m)
    
    print ('\nTip: Open up',filename,'with a text editor to see the serialized data.')
if __name__ == '__main__':
    main(sys.argv)

3.结果展示

3.1 控制台输出结果:

在这里插入图片描述

3.2生成的yml文件

%YAML:1.0
---
iterationNr: 100
strings:
   - "image1.jpg"
   - Awesomeness
   - "../data/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+00
   id: mydata1234

3.3生成的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>

4.代码解释

这里我们只讨论XML和YAML文件输入。您的输出(及其相应的输入)文件可能只有其中一个扩展名和结构。它们是两种可以序列化的数据结构:mapping(像STL map和Python字典)和元素序列(像STL vector)。它们之间的区别是,在一个映射中,每个元素都有一个惟一的名称,通过您可以访问它。对于序列,您需要遍历它们来查询特定的项。

s = cv.FileStorage(filename, cv.FileStorage_WRITE)
# or:
# s = cv.FileStorage()
# s.open(filename, cv.FileStorage_WRITE)

第二个参数是一个常量,指定可以对它们进行的操作类型:WRITE、READ或APPEND。文件名中指定的扩展名还决定将使用的输出格式。如果指定扩展名*.xml.gz*,输出甚至可能被压缩。

cv::FileStorage对象销毁时,文件会自动关闭。然而,你可以通过使用release函数来显式地调用它:s.release()

int itNr;
//fs["iterationNr"] >> itNr;
itNr = (int) fs["iterationNr"];
# 写
R = np.eye(3,3)
T = np.zeros((3,1))
s.write('R_MAT', R)
s.write('T_MAT', T)
# 读
R = s.getNode('R_MAT').mat()
T = s.getNode('T_MAT').mat()

对于序列,在第一个元素之前打印"["字符,在最后一个元素之后打印"]"字符(在C++中)。在Python中,调用FileStorage.startWriteStruct(structure_name, struct_type),其中struct_typecv2.FileNode_MAPcv2.FileNode_SEQ来开始写结构。调用FileStorage.endWriteStruct()来完成结构:

s.startWriteStruct('strings', cv.FileNode_SEQ)
for elem in ['image1.jpg', 'Awesomeness', '../data/baboon.jpg']:
    s.write('', elem)
s.endWriteStruct()

对于映射,操作是相同的,但现在我们使用“{”“}”分隔符(在C++中

s.startWriteStruct('Mapping', cv.FileNode_MAP)
s.write('One', 1)
s.write('Two', 2)
s.endWriteStruct()

为了从这些文件中读取数据,我们使用cv::FileNodecv::FileNodeIterator数据结构。cv::FileStorage类(或Python中的getNode()函数)的[]操作符返回cv::FileNode数据类型。如果节点是连续的,则可以使用cv::FileNodeIterator遍历所有项。在Python中,at()函数可用于寻址序列中的元素,size()函数返回序列的长度:

n = s.getNode('strings')
if (not n.isSeq()):
    print ('strings is not a sequence! FAIL', file=sys.stderr)
    exit(1)
for i in range(n.size()):
    print (n.at(i).string())

对于映射,你可以再次使用[]操作符(Python中的at()函数)来访问给定项(或者也使用>>操作符):

n = s.getNode('Mapping')
print ('Two',int(n.getNode('Two').real()),'; ')
print ('One',int(n.getNode('One').real()),'\n')
class MyData:
    def __init__(self):
        self.A = self.X = 0
        self.name = ''

在c++中,可以通过OpenCV I/O XML/YAML接口(就像OpenCV数据结构的情况一样)通过在类内外添加读和写函数来序列化它。在Python中,您可以通过在类中实现一个读写函数来实现这一点。内部部分:

def write(self, fs, name):
        fs.startWriteStruct(name, cv.FileNode_MAP|cv.FileNode_FLOW)
        fs.write('A', self.A)
        fs.write('X', self.X)
        fs.write('name', self.name)
        fs.endWriteStruct()
def read(self, node):
    if (not node.empty()):
        self.A = int(node.getNode('A').real())
        self.X = node.getNode('X').real()
        self.name = node.getNode('name').string()
    else:
        self.A = self.X = 0
        self.name = ''

这里可以看到,在read部分中,我们定义了如果用户试图读取一个不存在的节点会发生什么。在这种情况下,我们只返回默认的初始化值,但是更详细的解决方案是为实例返回一个- 1值的对象ID。

添加这几个函数后,使用>>操作符进行写操作,使用<<操作符进行读操作(或Python定义的输入/输出函数):

m = MyData()
m.write(s, 'MyData')
m.read(s.getNode('MyData'))

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

print ('Attempt to read NonExisting (should initialize the data structure',
            'with its default).')
m.read(s.getNode('NonExisting'))
print ('\nNonExisting =','\n',m)

标签:XML,fs,self,write,YAML,FileStorage,cv,输入,getNode
来源: https://blog.csdn.net/weixin_43229348/article/details/121679497