OpenCV编程->FileStorage解析

当保存浮点数据或XML/YML文件时,OpenCV的接口提供了FileStorage类。

       开始XML & YAML I/O 分析:

       下面贴上FileStorage类的源码。

class CV_EXPORTS_W FileStorage
{
public:
    //! file storage mode
    enum
    {
        READ=0, //! read mode
        WRITE=1, //! write mode
        APPEND=2, //! append mode
        MEMORY=4,
        FORMAT_MASK=(7<<3),
        FORMAT_AUTO=0,
        FORMAT_XML=(1<<3),
        FORMAT_YAML=(2<<3)
    };
    enum
    {
        UNDEFINED=0,
        VALUE_EXPECTED=1,
        NAME_EXPECTED=2,
        INSIDE_MAP=4
    };
    //! the default constructor
    CV_WRAP FileStorage();
    //! the full constructor that opens file storage for reading or writing
    CV_WRAP FileStorage(const string& source, int flags, const string& encoding=string());
    //! the constructor that takes pointer to the C FileStorage structure
    FileStorage(CvFileStorage* fs);
    //! the destructor. calls release()
    virtual ~FileStorage();

    //! opens file storage for reading or writing. The previous storage is closed with release()
    CV_WRAP virtual bool open(const string& filename, int flags, const string& encoding=string());
    //! returns true if the object is associated with currently opened file.
    CV_WRAP virtual bool isOpened() const;
    //! closes the file and releases all the memory buffers
    CV_WRAP virtual void release();
    //! closes the file, releases all the memory buffers and returns the text string
    CV_WRAP string releaseAndGetString();

    //! returns the first element of the top-level mapping
    CV_WRAP FileNode getFirstTopLevelNode() const;
    //! returns the top-level mapping. YAML supports multiple streams
    CV_WRAP FileNode root(int streamidx=0) const;
    //! returns the specified element of the top-level mapping
    FileNode operator[](const string& nodename) const;
    //! returns the specified element of the top-level mapping
    CV_WRAP FileNode operator[](const char* nodename) const;

    //! returns pointer to the underlying C FileStorage structure
    CvFileStorage* operator *() { return fs; }
    //! returns pointer to the underlying C FileStorage structure
    const CvFileStorage* operator *() const { return fs; }
    //! writes one or more numbers of the specified format to the currently written structure
    void writeRaw( const string& fmt, const uchar* vec, size_t len );
    //! writes the registered C structure (CvMat, CvMatND, CvSeq). See cvWrite()
    void writeObj( const string& name, const void* obj );

    //! returns the normalized object name for the specified file name
    static string getDefaultObjectName(const string& filename);

    Ptr<CvFileStorage> fs; //!< the underlying C FileStorage structure
    string elname; //!< the currently written element
    vector<char> structs; //!< the stack of written structures
    int state; //!< the writer state
};

 FileNode 存储XML或YAML文件中的每个节点,并用于读写。

class CV_EXPORTS_W_SIMPLE FileNode
{
public:
    //! type of the file storage node
    enum
    {
        NONE=0, //!< empty node
        INT=1, //!< an integer
        REAL=2, //!< floating-point number
        FLOAT=REAL, //!< synonym or REAL
        STR=3, //!< text string in UTF-8 encoding
        STRING=STR, //!< synonym for STR
        REF=4, //!< integer of size size_t. Typically used for storing complex dynamic structures where some elements reference the others
        SEQ=5, //!< sequence
        MAP=6, //!< mapping
        TYPE_MASK=7,
        FLOW=8, //!< compact representation of a sequence or mapping. Used only by YAML writer
        USER=16, //!< a registered object (e.g. a matrix)
        EMPTY=32, //!< empty structure (sequence or mapping)
        NAMED=64 //!< the node has a name (i.e. it is element of a mapping)
    };
    //! the default constructor
    CV_WRAP FileNode();
    //! the full constructor wrapping CvFileNode structure.
    FileNode(const CvFileStorage* fs, const CvFileNode* node);
    //! the copy constructor
    FileNode(const FileNode& node);
    //! returns element of a mapping node
    FileNode operator[](const string& nodename) const;
    //! returns element of a mapping node
    CV_WRAP FileNode operator[](const char* nodename) const;
    //! returns element of a sequence node
    CV_WRAP FileNode operator[](int i) const;
    //! returns type of the node
    CV_WRAP int type() const;

    //! returns true if the node is empty
    CV_WRAP bool empty() const;
    //! returns true if the node is a "none" object
    CV_WRAP bool isNone() const;
    //! returns true if the node is a sequence
    CV_WRAP bool isSeq() const;
    //! returns true if the node is a mapping
    CV_WRAP bool isMap() const;
    //! returns true if the node is an integer
    CV_WRAP bool isInt() const;
    //! returns true if the node is a floating-point number
    CV_WRAP bool isReal() const;
    //! returns true if the node is a text string
    CV_WRAP bool isString() const;
    //! returns true if the node has a name
    CV_WRAP bool isNamed() const;
    //! returns the node name or an empty string if the node is nameless
    CV_WRAP string name() const;
    //! returns the number of elements in the node, if it is a sequence or mapping, or 1 otherwise.
    CV_WRAP size_t size() const;
    //! returns the node content as an integer. If the node stores floating-point number, it is rounded.
    operator int() const;
    //! returns the node content as float
    operator float() const;
    //! returns the node content as double
    operator double() const;
    //! returns the node content as text string
    operator string() const;

    //! returns pointer to the underlying file node
    CvFileNode* operator *();
    //! returns pointer to the underlying file node
    const CvFileNode* operator* () const;

    //! returns iterator pointing to the first node element
    FileNodeIterator begin() const;
    //! returns iterator pointing to the element following the last node element
    FileNodeIterator end() const;

    //! reads node elements to the buffer with the specified format
    void readRaw( const string& fmt, uchar* vec, size_t len ) const;
    //! reads the registered object and returns pointer to it
    void* readObj() const;

    // do not use wrapper pointer classes for better efficiency
    const CvFileStorage* fs;
    const CvFileNode* node;
};
节点操作申明。

/*!
 File Node Iterator

 The class is used for iterating sequences (usually) and mappings.
 */
class CV_EXPORTS FileNodeIterator
{
public:
    //! the default constructor
    FileNodeIterator();
    //! the full constructor set to the ofs-th element of the node
    FileNodeIterator(const CvFileStorage* fs, const CvFileNode* node, size_t ofs=0);
    //! the copy constructor
    FileNodeIterator(const FileNodeIterator& it);
    //! returns the currently observed element
    FileNode operator *() const;
    //! accesses the currently observed element methods
    FileNode operator ->() const;

    //! moves iterator to the next node
    FileNodeIterator& operator ++ ();
    //! moves iterator to the next node
    FileNodeIterator operator ++ (int);
    //! moves iterator to the previous node
    FileNodeIterator& operator -- ();
    //! moves iterator to the previous node
    FileNodeIterator operator -- (int);
    //! moves iterator forward by the specified offset (possibly negative)
    FileNodeIterator& operator += (int ofs);
    //! moves iterator backward by the specified offset (possibly negative)
    FileNodeIterator& operator -= (int ofs);

    //! reads the next maxCount elements (or less, if the sequence/mapping last element occurs earlier) to the buffer with the specified format
    FileNodeIterator& readRaw( const string& fmt, uchar* vec,
                               size_t maxCount=(size_t)INT_MAX );

    const CvFileStorage* fs;
    const CvFileNode* container;
    CvSeqReader reader;
    size_t remaining;
};


测试源码:

// open file storage for writing. Type of the file is determined from the extension
 FileStorage fs("test.yml", FileStorage::WRITE);
 fs << "test_int" << 5 << "test_real" << 3.1 << "test_string" << "ABCDEFGH";
 fs << "test_mat" << Mat::eye(3,3,CV_32F);

 fs << "test_list" << "[" << 0.0000000000001 << 2 << CV_PI << -3435345 << "2-502 2-029 3egegeg" <<
 "{:" << "month" << 12 << "day" << 31 << "year" << 1969 << "}" << "]";
 fs << "test_map" << "{" << "x" << 1 << "y" << 2 << "width" << 100 << "height" << 200 << "lbp" << "[:";

 const uchar arr[] = {0, 1, 1, 0, 1, 1, 0, 1};
 fs.writeRaw("u", arr, (int)(sizeof(arr)/sizeof(arr[0])));

 fs << "]" << "}";
读入数据如下:

\verbatim
 %YAML:1.0
 test_int: 5
 test_real: 3.1000000000000001e+00
 test_string: ABCDEFGH
 test_mat: !!opencv-matrix
     rows: 3
     cols: 3
     dt: f
     data: [ 1., 0., 0., 0., 1., 0., 0., 0., 1. ]
 test_list:
     - 1.0000000000000000e-13
     - 2
     - 3.1415926535897931e+00
     - -3435345
     - "2-502 2-029 3egegeg"
     - { month:12, day:31, year:1969 }
 test_map:
     x: 1
     y: 2
     width: 100
     height: 200
     lbp: [ 0, 1, 1, 0, 1, 1, 0, 1 ]
 \endverbatim

读入源码:

// open file storage for reading.
 // Type of the file is determined from the content, not the extension
 FileStorage fs("test.yml", FileStorage::READ);
 int test_int = (int)fs["test_int"];
 double test_real = (double)fs["test_real"];
 string test_string = (string)fs["test_string"];

 Mat M;
 fs["test_mat"] >> M;

 FileNode tl = fs["test_list"];
 CV_Assert(tl.type() == FileNode::SEQ && tl.size() == 6);
 double tl0 = (double)tl[0];
 int tl1 = (int)tl[1];
 double tl2 = (double)tl[2];
 int tl3 = (int)tl[3];
 string tl4 = (string)tl[4];
 CV_Assert(tl[5].type() == FileNode::MAP && tl[5].size() == 3);

 int month = (int)tl[5]["month"];
 int day = (int)tl[5]["day"];
 int year = (int)tl[5]["year"];

 FileNode tm = fs["test_map"];

 int x = (int)tm["x"];
 int y = (int)tm["y"];
 int width = (int)tm["width"];
 int height = (int)tm["height"];

 int lbp_val = 0;
 FileNodeIterator it = tm["lbp"].begin();

 for(int k = 0; k < 8; k++, ++it)
    lbp_val |= ((int)*it) << k;

1、XML和YAML可以嵌套的两种集合类型:映射(mappings)、序列(sequences)。映射集合类似STL中的std::map和Python中的字典,序列集合类似STL中std::vector和 Python的序列;

2、当写入映射结构的数据时,节点的值(value)紧跟着节点的键(key);当写入序列结构的数据时,逐一写入即可;

3、写入映射结构数据时,格式如下:fs << "{" << element_key << element_value << "}"

4、写入序列结构数据时,格式如下:fs << "[" << element_value << …… << "]"

5、写入映射、序列嵌套的数据时,以"{:"代替"{","[:" 代替 "["。








你可能感兴趣的:(opencv,FileStorage)