OpenCV —資料持久化: FileStorage類的資料存取操作與示例
OpenCV —FileStorage類的資料讀寫操作與示例
OpenCV的許多應用都需要使用資料的儲存於讀取,例如經過3D校準後的相機,需要儲存校準結果矩陣,以方便下次呼叫該資料;基於機器學習的應用,同樣需要將學習得到的引數儲存等。OpenCV通過XML/YAML格式實現資料持久化。本文簡要梳理了使用FileStorage類進行基本資料持久化操作,給出了示例程式碼。
主要內容包括:
FileStorage類
- 建構函式
- operator <<
- FileStorage::open
- FileStorage::isOpened
- FileStorage::release
- FileStorage::getFirstTopLevelNode
- FileStorage::root
- FileStorage::operator[]
示例程式碼
- 建立寫入器、建立讀取器
- 寫入數值、寫入矩陣、寫入自定義資料結構、寫入當前時間
- 讀取數值、讀取矩陣、讀取自定義資料結構、讀取當前時間
- 關閉寫入器、關閉讀取器
FileStorage類
FileStorage類將各種OpenCV資料結構的資料儲存為XML 或 YAML格式。同時,也可以將其他型別的數值資料儲存為這兩種格式。
建構函式
FileStorage類的建構函式為:
cv::FileStorage(const string& source, int flags, const string& encoding=string());
引數:
source –儲存或讀取資料的檔名(字串),其副檔名(.xml 或 .yml/.yaml)決定檔案格式。
flags – 操作模式,包括:
- FileStorage::READ 開啟檔案進行讀操作
- FileStorage::WRITE 開啟檔案進行寫操作
- FileStorage::APPEND開啟檔案進行附加操作
- FileStorage::MEMORY 從source讀資料,或向內部快取寫入資料(由FileStorage::release返回)
encoding – 檔案編碼方式。目前不支援UTF-16 XML 編碼,應使用 8-bit 編碼。
寫資料operator <<
向filestorage中寫入資料
template<typename_Tp> FileStorage& operator<<(FileStorage& fs, const _Tp& value)
template<typename_Tp> FileStorage& operator<<(FileStorage& fs, const vector<_Tp>& vec)
引數:以下程式碼分別演示寫入數值、矩陣、多個變數、當前時間和關閉檔案:fs – 已經開啟的用於寫資料的file storage物件
value – 待寫入fs 的資料.
vec – 待寫入fs 的向量值
// 1.create our writter
cv::FileStorage fs("test.yml", FileStorage::WRITE);
// 2.Save an int
int imageWidth= 5;
int imageHeight= 10;
fs << "imageWidth" << imageWidth;
fs << "imageHeight" << imageHeight;
// 3.Write a Mat
cv::Mat m1= Mat::eye(3,3, CV_8U);
cv::Mat m2= Mat::ones(3,3, CV_8U);
cv::Mat resultMat= (m1+1).mul(m1+2);
fs << "resultMat" << resultMat;
// 4.Write multi-variables
cv::Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
cv::Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
// 5.Save local time
time_t rawtime; time(&rawtime); //#include <time.h>
fs << "calibrationDate" << asctime(localtime(&rawtime));
// 6.close the file opened
fs.release();
生成的檔案test.yml
FileStorage::open
開啟一個檔案
boolFileStorage::open(const string& filename, int flags, const string&encoding=string())
引數:
filename – 待開啟的檔名,其副檔名(.xml 或 .yml/.yaml) 決定檔案格式(XML 或 YAML)
flags – 操作模式。見建構函式
encoding – 檔案編碼方式。
// open a file
cv::FileStorage fs;
fs.open("test.yml",FileStorage::WRITE);
// ... some process here
fs.release();
FileStorage::isOpened
檢查檔案是否已經開啟,呼叫:
boolFileStorage::isOpened()
返回:
ture – 如果物件關聯了當前檔案;
false – 其他情況。
嘗試開啟檔案後呼叫此方法是個比較好的做法。
// Checks whether the file is opened
cv::FileStorage fs;
fs.open("test.yml",FileStorage::WRITE);
bool flag = fs.isOpened();
cout<<"flag = "<<flag<<endl<<endl;
// if failed to open a file
if(!fs.isOpened()){
cout<<"failed to open file test.yml "<<endl<<endl;
return 1;
}
執行結果:
FileStorage::release
儲存或讀取操作完成後,需要關閉檔案並釋放快取,呼叫
void FileStorage::release()
cv::FileStorage fs("test.yml", fs::WRITE);
//... some processing here
fs.release();
FileStorage::getFirstTopLevelNode
返回對映(mapping)頂層的第一個元素:
FileStorage::getFirstTopLevelNode()
// open a file for reading
fs.open("test.yml", FileStorage::READ);
// get the first top level node
int firstNode = fs.getFirstTopLevelNode();
cout<<"the First Top Level Node = "<<firstNode<<endl<<endl;
執行結果
FileStorage::root
返回頂層對映(mapping)
FileNode FileStorage::root(int streamidx=0)
引數:
streamidx – 從0開始的字串索引。大部分情況檔案中只有一個串,但YAML支援多個串,因此可以有多個。
Returns: 頂層對映
讀資料:FileStorage::operator[]
返回指定的頂層對映元素
FileNode FileStorage::operator[](const string& nodename) const
FileNode FileStorage::operator[](const char* nodename) const
引數:
nodename – 檔案節點名(見下文FileNode類)
返回:名稱為nodename的節點資料
// read data using operator []
cv::FileStorage fs("test.yml", FileStorage::READ);
int width;
int height;
fs["imageWidth"]>>width;
fs["imageHeight"]>>height;
cout<<"width readed = "<<width<<endl;
cout<<"height readed = "<<height<<endl<<endl;
// read Mat
cv::Mat resultMatRead;
fs["resultMat"]>>resultMatRead;
cout<<"resultMat readed = "<<resultMatRead<<endl<<endl;
cv::Mat cameraMatrixRead,distCoeffsRead;
fs["cameraMatrix"]>>cameraMatrixRead;
fs["distCoeffs"]>>distCoeffsRead;
cout<<"cameraMatrix readed = "<<cameraMatrixRead<<endl;
cout<<"distCoeffs readed = "<<distCoeffsRead<<endl<<endl;
// read string
string timeRead;
fs["calibrationDate"]>>timeRead;
cout<<"calibrationDate readed = "<<timeRead<<endl<<endl;
fs.release();
執行結果