寫教學的最大目的是教會未來的自己

openCV的XML 資料儲存教學

 

最近正在研究 openCV 的資料儲存(其實是幾個月前了),所以有感寫了這篇

其實類似的文章已經有許多,我這次只是整合後再發表一些自己的意見。

 

參考資料

http://blog.csdn.net/ecocn/article/details/8077012

http://blog.csdn.net/colorpanda/article/details/5969780

http://wiki.opencv.org.cn/index.php/Cxcore数据保存和运行时类型信息

 

一開始,我只是希望能把 我透過 openCV 跑 SURF 的結果儲存起來,避免每次都要重新跑,所以我找到了第一個參考資料網頁

基本上十分簡單,如果只是cvSeq 這個資料型態的都可以自使用。

 

但是之後我發現了一個問題,當你建立一個資料架構型態都不同的時候怎麼處理,我不會自建cvSeq ,所以 我去找了許多網站,所以就有了第二 第三個參考網頁

建議一邊依照 第二個網頁來練習,並且參照第三個網頁的資料來弄。

 

OK 進入主題

首先,我們要先宣告建立XML 檔案,並且設定是要讀取還是寫入,如果要讀取把最後一個參數改成 CV_STORAGE_READ,第一個參數是黨明,第二個參數是宣告一塊記憶體位置,似乎填0就可以了

CvFileStorage* fs=cvOpenFileStorage("ms.xml",0,CV_STORAGE_WRITE);  

在最後要加上

cvReleaseFileStorage(&fs);

來收工

 

在這段程式碼中間 就開始了你的XML的讀取與寫入之旅

有寫過網頁的人 應該比較清楚,XML 其實就是一個樹狀架構以 <XXX> 開頭 </XXX>結尾,所以現在就是要來開始設計自己的樹

 

底下幾個比較常用的function ,我一一作介紹

cvWriteInt(fs,name,10); 

看名字就知道是儲存整數的function,第一個參數放XML 檔頭,第二個放名稱 第三個放你要寫入的資料

執行後 會產生 <name>10</name>的結果,這是處理整數的用法bool 也同要要用這個方法。

相同用法的有 cvWriteReal() 和cvWriteString()

與這個相對應的讀取方法則是

int value = cvReadIntByName(fs,0,"Value",1);   第一個參數同樣是 XML 黨頭,第二個參數比較重要是CvFileNode* map,就是XML的指標,因為在樹狀架構下你是要從上網下找,你可以指定從哪裡開始,如果放0就是從最上層開始,通常如果你在儲存大量資料時,你可能會有自建資料型態,會有固定名字,這時CvFileNode* map 就很重要,這之後我在做說明

相同用法的有 cvReadRealByName() 和cvReadStringByName()

 

介紹完了單一變數的

這次介紹在一個<> </>中寫入多筆資料的方法

 

底下這是一個基本用法

cvStartWriteStruct(fs,"data",CV_NODE_SEQ); 

…..

cvEndWriteStruct(fs)

 

建立一個 <data> </data> 的資料型態,中間可以放多筆資料 以 space 隔開,CV_NODE_SEQ 是表示資料是個array,如果你是用在一個物件的開頭集結尾,中間有不同變數請改用CV_NODE_MAP

在這中間 可以放cvWriteInt(fs,0,10);  把第二個參數改為0 就不會出現<> ,當然這方法不太好用

可以改用cvWriteRawData( fs, data,size, "u" );   第二個參數是 資料的指標 (char * 等等),第三個參數是有幾筆資料,第四個參數比較重要,要確定幾位員和以怎樣儲存

詳細說明請看第三個參考網頁

  • u' – 8位無符號數。
  • 'c' – 8位符號數。
  • 'w' – 16位無符號數。
  • 's' – 16位符號數。
  • 'i' – 32位符號數。
  • 'f' – 單精度浮點數。
  • 'd' – 雙精度浮點數。
  • 'r' – 指針。輸入的帶符號的低32位整數。 這個類型常被用來存儲結構體之間的鏈接。

根據實驗 幾個byte 要確定,其他的讀寫時相同就可以了

 

再來是資料讀取,讀取前我們要先抓node 就是XML的結點

下面這個例子中map 是CvFileNode * ,我要從這個node 底下找到一個 名為data的node,並且把資料讀取出來

CvFileNode* X =cvGetFileNodeByName( fs,    map,"data");
cvReadRawData( fs, X,    data, "u" );//u

 

如果以第一種方法的讀取可以改成這樣,就是從map 底下找一個 名為Value的node 並且把資料讀取出來

int value = cvReadIntByName(fs,map,"Value",1);

 

 

 

 

接下來是建議

XML 的資料寫入速度很快,但是讀取比較花費時間,系統在load的時候會先解析所有的樹狀架構,所以你如果資料量大會很花費時間

我個人要處理500張圖 有17萬個點,就有17萬個array 讀取時間鬼扯慢,超過兩分鐘,所以最後我先把所有array 合併成寫入向下列這樣寫法,之後我讀取時再來分割,這樣速度會快許多,我這樣修改後 賭取只需3~5秒

    cvStartWriteStruct(fs,"data",CV_NODE_SEQ);  
    for(int i=0;i<totalPointData;i++)
    {
        cvWriteRawData( fs, pointTable[i]->data,pointTable[i]->size , "u" );
    }
    cvEndWriteStruct(fs);

Post to Twitter Post to Plurk Post to Facebook Send Gmail

2 Responses to openCV的XML 資料儲存教學

  • 不好意思
    跟您請教一下
    我是用SIFT和ORB演算法去產生特徵點和特徵點描述存成XML
    我現在出的問題是
    SIFT特徵點和描述都能有辦法讀取
    但ORB卻只能讀到特徵點
    描述部分載入都是空白
    依您看是是否能點出我出了甚麼問題

Leave a Reply

Copyright © 2024. All Rights Reserved.

歡迎光臨
初音