1. 程式人生 > >OpenCV —資料持久化: FileStorage類的資料存取操作與示例

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();

執行結果