1. 程式人生 > >OpenCV儲存成XML(FileStorage)和CSV(過載

OpenCV儲存成XML(FileStorage)和CSV(過載

XML檔案(使用FileStorage類)

使用OpenCV時不僅要儲存影像結果,往往也需要儲存中間的矩陣結果,而OpenCV的imwrite函式只支援CV8U型別的資料(使用OpenCV儲存其他型別Mat的時候,程式不會報錯,但是無法生成結果檔案),因此會給工作帶來很多不便。OpenCV在2.0以後的版本中提供了FileStorage類,供使用者直接使用,儲存為XML/YAML檔案。

儲存XML

儲存示例如下:

Mat mat = Mat::eye(Size(12,12), CV_8UC1);
FileStorage fs("f:\\vocabulary.xml", FileStorage::WRITE
); fs << "vocabulary" << mat; fs.release();

得到結果檔案如下所示:

<?xml version="1.0"?>
<opencv_storage>
<vocabulary type_id="opencv-matrix">
  <rows>12</rows>
  <cols>12</cols>
  <dt>u</dt>
  <data>
    1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
    0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
    0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
    0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
    0 0 0 0 0 0 0 1</data
>
</vocabulary> </opencv_storage>

需要注意的是,因為儲存的結果為xml檔案,所以再儲存的時候需要給定標籤,格式就是下面的形式,先儲存標籤內容,再儲存矩陣:

fs << "vocabulary" << mat;

讀取XML

同樣使用FileStorage類可以直接獲取儲存的xml檔案內容。
讀取示例如下:

FileStorage fs(".\\vocabulary.xml", FileStorage::READ);
Mat mat_vocabulary;
fs["vocabulary"] >> mat_vocabulary;

讀取檔案的時候同樣要給定標籤內容,這裡通過中括號[]給定:

fs["vocabulary"] >> mat_vocabulary;

CSV檔案

很多時候,直接使用CSV檔案相比XML更方便,使用XML儲存得到的資料,無論是檢視(excel檢視,XML中矩陣不是格式化的)還是接著使用別的工具處理(例如matlab),都可以快速的讀取,而XML需要解析則比較繁瑣。那麼該如何儲存CSV檔案呢,對儲存的CSV檔案又應該如何讀取呢,請看下文分解。

儲存CSV檔案

OpenCV提供了結果儲存的格式化函式format,使用format我們就可以根據自己想要的格式列印和儲存資料了。

先直接看儲存函式,再來分析具體含義吧:

ofstream file("test.csv");
file << format(mat, Formatter::FMT_CSV);
file.close();

根據上面的程式碼只用ofstream物件開啟要寫入的csv檔案,再直接寫入資料即可,需要注意的是,接入的矩陣用format格式化,format函式第二個引數表示格式型別,這裡選擇CSV格式即Formatter::FMT_CSV

儲存結果如圖所示:
CSV

這裡儲存格式為定義在Formatter類中的列舉型別,總共有6中選項,各位讀者可以根據自己的需求選擇。

class CV_EXPORTS Formatter
{
public:
    enum { FMT_DEFAULT = 0,
           FMT_MATLAB  = 1,
           FMT_CSV     = 2,
           FMT_PYTHON  = 3,
           FMT_NUMPY   = 4,
           FMT_C       = 5
         };

    virtual ~Formatter();

    virtual Ptr<Formatted> format(const Mat& mtx) const = 0;

    virtual void set32fPrecision(int p = 8) = 0;
    virtual void set64fPrecision(int p = 16) = 0;
    virtual void setMultiline(bool ml = true) = 0;

    static Ptr<Formatter> get(int fmt = FMT_DEFAULT);

};

讀取CSV資料

在儲存為CSV格式後該如何讀取呢,這裡可以使用OpenCV中ml模組的TrainData類的函式讀取。具體程式碼如下所示,第二行為載入資料,引數0表示沒有標題行,第三行獲取得到的資料。

Ptr<TrainData> train_data;
train_data = TrainData::loadFromCSV("test.csv", 0); 
Mat m = train_data->getTrainSamples();
cout << format(m, Formatter::FMT_CSV) << endl;

程式碼執行結果為:
這裡寫圖片描述