利用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;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM