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);
不好意思
跟您請教一下
我是用SIFT和ORB演算法去產生特徵點和特徵點描述存成XML
我現在出的問題是
SIFT特徵點和描述都能有辦法讀取
但ORB卻只能讀到特徵點
描述部分載入都是空白
依您看是是否能點出我出了甚麼問題
您好,請先確認,在不輪存獨取,您最原始的資料是否就可以正常讀出資料
在這篇,我自己是使用自建的資料結構,再透過我寫的方法兜出存讀檔的功能
不過要先說明一下,如果資料量太大,這種讀寫方法很慢
如果您的資料是使用cvseq可以用另一種方式讀取
可以參考
http://www.pupuliao.info/2013/05/opencv-surf-儲存方式/