OpenCV FileStorage 用法與 YAML 檔案讀取寫入範例

本篇介紹如何使用 OpenCV 的 FileStorage 來做 YAML 檔案格式的寫入與讀取,在 OpenCV 許多應用都需要使用資料的儲存於讀取,例如相機的3D校正需要儲存校正後的結果矩陣,以利下次使用;在機器學習的應用上需要將訓練學習得到的參數保存等。OpenCV 提供了 XML/YAML 檔案格式作儲存與讀取,以下將介紹如何使用 FileStorage 來讀取與寫入 YAML。

FileStorage 使用介紹

FileStorage 的使用流程如下:

  1. 初始化一個 FileStorage 的變數並且開檔
  2. 使用 << 進行資料的寫入,>> 進行資料讀取,類似 C++ 中的檔案操作
  3. 使用 FileStorage::release() 函數釋放記憶體與關檔

使用 FileStorage 寫入資料

以下範例示範開檔、寫入int數值、寫入矩陣、寫入系統時間,最後關檔。

opencv-FileStorage-write.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// g++ opencv-FileStorage-write.cpp `pkg-config --cflags --libs opencv`
#include <time.h>
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

bool writeYaml() {
std::string filename = "output.yaml";
cv::FileStorage fs(filename, FileStorage::WRITE);
if (!fs.isOpened()) {
cout << "failed to open file " << filename << endl;
return false;
}

// write int
int imageWidth= 5;
int imageHeight= 10;
fs << "imageWidth" << imageWidth;
fs << "imageHeight" << imageHeight;

// 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;

// write multi-variables
cv::Mat cameraMatrix = (Mat_<double>(3,3) << 700, 0, 320, 0, 700, 240, 0, 0, 1);
cv::Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;

// write local time
time_t rawtime;
time(&rawtime); // #include <time.h>
fs << "calibrationDate" << asctime(localtime(&rawtime));

fs.release();
return true;
}

int main(int argc, const char *argv[])
{
writeYaml();
return 0;
}

使用 FileStorage 讀取資料

opencv-FileStorage-read.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// g++ opencv-FileStorage-read.cpp `pkg-config --cflags --libs opencv`
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

bool readYaml() {
std::string filename = "output.yaml";
cv::FileStorage fs(filename, FileStorage::READ);
if (!fs.isOpened()) {
cout << "failed to open file " << filename << endl;
return false;
}

int width;
int height;
fs["imageWidth"] >> width;
fs["imageHeight"] >> height;
cout << "width = " << width << endl;
cout << "height = " <<height << endl;

// read Mat
cv::Mat resultMatRead;
fs["resultMat"] >> resultMatRead;
cout << "resultMat = \n" << resultMatRead << endl;

cv::Mat cameraMatrix, distCoeffs;
fs["cameraMatrix"] >> cameraMatrix;
fs["distCoeffs"] >> distCoeffs;
cout << "cameraMatrix = \n" << cameraMatrix << endl;
cout << "distCoeffs = \n" << distCoeffs << endl;

// read string
string timeRead;
fs["calibrationDate"] >> timeRead;
cout << "calibrationDate = " << timeRead << endl;

fs.release();
return true;
}

int main(int argc, const char *argv[])
{
readYaml();
return 0;
}

輸出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
width = 5
height = 10
resultMat =
[ 6, 2, 2;
2, 6, 2;
2, 2, 6]
cameraMatrix =
[700, 0, 320;
0, 700, 240;
0, 0, 1]
distCoeffs =
[0.1;
0.01;
-0.001;
0;
0]
calibrationDate = Wed Dec 18 23:04:36 2019

參考
[1] OpenCV: cv::FileStorage Class Reference
https://docs.opencv.org/3.4.8/da/d56/classcv_1_1FileStorage.html
[2] OpenCV —數據持久化: FileStorage類的數據存取操作與示例 - iracer的博客
https://blog.csdn.net/iracer/article/details/51339377
[3] 使用OpenCV的FileStorage模塊持久化存取數據(Python)
http://zhaoxuhui.top/blog/2018/06/29/PythonOpenCVFileStorage.html

其它相關文章推薦
怎麼查詢 OpenCV 的版本
如何看OpenCV當初編譯的編譯參設定
OpenCV trace VideoCapture 流程