1. 程式人生 > >opencv學習筆記(二)-對xml和yaml檔案的讀寫操作

opencv學習筆記(二)-對xml和yaml檔案的讀寫操作

一.xml和yaml的簡單介紹

       所謂的xml,就是eXtensible Markup Language, 翻譯成中文就是“可擴充套件標識語言“。首先XML是一種元標記語言,所謂“元標記”就是開發者可以根據自己的需要定義自己的標記,比如開發者可以定義如下標記<book> <name>,任何滿足xml命名規則的名稱都可以標記,這就為不同的應用程式打開了的大門。 第二xml是一種語義/結構化語言。它描述了文件的結構和語義。

     XML可利用於資料交換 主要是因為XML表示的資訊獨立於平臺的,這裡的平臺即可以理解為不同的應用程式也可以理解為不同的作業系統;它描述了一種規範,利用它Microsoft的word文件可以和Adobe 的Acrobat交換資訊,可以和資料庫交換資訊。

   XML表示的結構化資料。 
  對於大型複雜的文件,xml 是一種理想語言,不僅允許指定文件中的詞彙,還允許指定元素之間的關係。比如可以規定一個author元素必須有一個name子元素。可以規定企業的業務必須有包括什麼子業務。 
XML文件。 XML文件有DTD和XML文字組成,所謂DTD(Document Type Definition ),簡單的說就是一組標記符的語法規則.,表明XML文字是怎麼樣組織的,比如DTD可以表示一個<book>必須有一個子標記<author>, 可以有或者沒有子標記<pages> 等等。當然一個簡單的XML文字可以沒有DTD。下面是一個簡單的xml文字。 <? Xml version=”1.0” standalone=”yes”> <book> haha </book> 其中以?開始並結尾的是程序說明。Standalone表示外圍裝置。這裡外圍裝置可以理解為該XML文字沒有應用其他的檔案。因為XML檔案可以外部應用DTD等外部資料。更多資訊請參考:

點選開啟連結


     和GNU一樣,YAML是一個遞迴著說“不”的名字。不同的是,GNU對UNIX說不,YAML說不的物件是XML。YAML不是XML。

為什麼不是XML呢?因為:

  • YAML的可讀性好。
  • YAML和指令碼語言的互動性好。
  • YAML使用實現語言的資料型別。
  • YAML有一個一致的資訊模型。
  • YAML易於實現。

上面5條也就是XML不足的地方。同時,YAML也有XML的下列優點:

  • YAML可以基於流來處理;
  • YAML表達能力強,擴充套件性好。

總之,YAML試圖用一種比XML更敏捷的方式,來完成XML所完成的任務。

更多的內容及規範參見http://www.yaml.org


二.opencv中對xml 和yaml檔案的讀寫資料結構介紹

    XML\YAML檔案在OpenCV中的資料結構為FileStorage,更多參考:點選開啟連結

   開啟寫操作:

FileStorage fs("test.yml", FileStorage::WRITE);

開啟讀操作:
FileStorage fs2("test.yml", FileStorage::READ);

三.對xml和yaml檔案的讀寫操作及其示例

     寫操作示例只是對yaml做演示,xml的操作也一樣:

示例程式碼:

#include "opencv2/opencv.hpp"
#include <time.h>

using namespace cv;

int main(int, char** argv)
{
    FileStorage fs("test.yml", FileStorage::WRITE);

    fs << "frameCount" << 5;
    time_t rawtime; time(&rawtime);
    fs << "calibrationDate" << asctime(localtime(&rawtime));
    Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
    Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
    fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
    fs << "features" << "[";
    for( int i = 0; i < 3; i++ )
    {
        int x = rand() % 640;
        int y = rand() % 480;
        uchar lbp = rand() % 256;

        fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
        for( int j = 0; j < 8; j++ )
            fs << ((lbp >> j) & 1);
        fs << "]" << "}";
    }
    fs << "]";
    fs.release();
    return 0;
}

寫入的xml文件內容:
<?xml version="1.0"?>
<opencv_storage>
<frameCount>5</frameCount>
<calibrationDate>"Fri May 03 11:34:09 2013
"</calibrationDate>
<cameraMatrix type_id="opencv-matrix">
  <rows>3</rows>
  <cols>3</cols>
  <dt>d</dt>
  <data>
    1000. 0. 320. 0. 1000. 240. 0. 0. 1.</data></cameraMatrix>
<distCoeffs type_id="opencv-matrix">
  <rows>5</rows>
  <cols>1</cols>
  <dt>d</dt>
  <data>
    1.0000000000000001e-001 1.0000000000000000e-002
    -1.0000000000000000e-003 0. 0.</data></distCoeffs>
<features>
  <_><x>41</x>
    <y>227</y>
    <lbp>
      0 1 1 1 1 1 0 1</lbp></_>
  <_><x>260</x>
    <y>449</y>
    <lbp>
      0 0 1 1 0 1 1 0</lbp></_>
  <_><x>598</x>
    <y>78</y>
    <lbp>
      0 1 0 0 1 0 1 0</lbp></_></features>
</opencv_storage>

讀操作:
FileStorage fs2("test.yml", FileStorage::READ);

// first method: use (type) operator on FileNode.
int frameCount = (int)fs2["frameCount"];

std::string date;
// second method: use FileNode::operator >>
fs2["calibrationDate"] >> date;

Mat cameraMatrix2, distCoeffs2;
fs2["cameraMatrix"] >> cameraMatrix2;
fs2["distCoeffs"] >> distCoeffs2;

cout << "frameCount: " << frameCount << endl
     << "calibration date: " << date << endl
     << "camera matrix: " << cameraMatrix2 << endl
     << "distortion coeffs: " << distCoeffs2 << endl;

FileNode features = fs2["features"];
FileNodeIterator it = features.begin(), it_end = features.end();
int idx = 0;
std::vector<uchar> lbpval;

// iterate through a sequence using FileNodeIterator
for( ; it != it_end; ++it, idx++ )
{
    cout << "feature #" << idx << ": ";
    cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
    // you can also easily read numerical arrays using FileNode >> std::vector operator.
    (*it)["lbp"] >> lbpval;
    for( int i = 0; i < (int)lbpval.size(); i++ )
        cout << " " << (int)lbpval[i];
    cout << ")" << endl;
}
fs.release();

讀取示例:


四.結束語和參考資料

    對xml的操作中,嘗試了寫入一幅圖片,然後讀取並顯示出來。結果是寫入成功了,但讀取後顯示失敗,提示說沒有找到使用者自定義的從fileNode型別到Mat型別的轉換方式,這需要自己定義嗎,opencv有沒有自己定義好的,可以直接呼叫,求大神們指教。

參考資料

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