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。
儲存結果如圖所示:
這裡儲存格式為定義在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;
程式碼執行結果為: