#转载于https://blog.csdn.net/learning_tortosie/article/details/97815514
数据存储
OpenCV提供了一种序列化和反序列化的机制,用于将不同数据类型的数据以YAML或XML格式写入磁盘或者从磁盘读取。这种方法可以用来加载或者保存任何OpenCV的数值变量(包括基本数据变量,像int和float等)到一个文件中。
上述文件读写的基本机制是建立在cv::FileStorage对象基础上的,cv::FileStorage实际代表磁盘中的一个文件,但与普通方式不同的是,它让人们以一种简单而自然的方式访问文件中的数据。
cv::FileStorage的写入
cv::FileStorage对象代表一个YAML或XML格式的文件。你可以给定文件名参数创建一个cv::FileStorage对象或者使用默认构造函数创建一个未打开的cv::FileStorage对象,稍后再使用cv::FileStorage::open()函数打开。flag参数可以为cv::FileStorage::WRITE或cv::FileStorage::APPEND。
FileStorage::open(string fileName, int flag);
- 1
一旦成功打开了你想要写入的文件,便可以像对标准输出流输出数据一样使用操作符cv::FileStorage::operator<<()进行写入操作。你可以以这种简单的方式写入,是因为函数内部为你完成了许多复杂的工作。
cv::FileStorage内部数据的存储主要有两种方式,“mapping”(键/值对)和“sequence”(一系列未命名的条目)。在最顶层,你写入的数据都在一个mapping中,你可以放置其他的mapping或sequence,甚至在mapping中继续放入mapping等,只要你愿意。
myFileStorage << "someInteger" << 27; //保存一个整数
myFileStorage << "anArray" << cv::Mat::eye(3,3,CV_32F); //保存一个数组
- 1
- 2
如果要创建一个序列条目,首先你得为它提供一个string类型的名字,接下来才是序列数据。条目内容可以是数字(整型或浮点型等),一个字符串或别的OpenCV数据类型。
如果你要创建一个新的mapping或sequence,可以使用特殊符号{(用于mapping)或[(用于sequence)。一旦开始创建,就可以为其添加元素,最终以}或]分别结束一个mapping或sequence。
myFileStorage << "theCat" << "{";
myFileStorage << "fur" << "gray" << "eyes" << "green" << "weightLbs" << 16;
myFileStorage << "}";
- 1
- 2
- 3
一旦完成创建一个mapping,需要按顺序输入条目名以及对应的值。如果创建的是sequence,只需要一个接一个地输入元素即可,知道sequence结束。
myFileStorage << “theTeam" << "[";
myFileStorage << "eddie" << "tom" << "scott";
myFileStorage << "]";
- 1
- 2
- 3
一旦完成写工作,便可以使用成员函数cv::FileStorage::release()关闭文件。
示例:使用cv::FileStorage创建一个test.yaml文件
#include <opencv2/opencv.hpp>
#include <time.h>
using namespace cv;
int main() {
FileStorage <span class="token function">fs</span><span class="token punctuation">(</span><span class="token string">"test.yaml"</span><span class="token punctuation">,</span> FileStorage<span class="token punctuation">:</span><span class="token punctuation">:</span>WRITE<span class="token punctuation">)</span><span class="token punctuation">;</span>
fs <span class="token operator"><<</span> <span class="token string">"frameCount"</span> <span class="token operator"><<</span> <span class="token number">5</span><span class="token punctuation">;</span>
time_t rawtime<span class="token punctuation">;</span> <span class="token function">time</span><span class="token punctuation">(</span><span class="token operator">&</span>rawtime<span class="token punctuation">)</span><span class="token punctuation">;</span>
fs <span class="token operator"><<</span> <span class="token string">"calibrationDate"</span> <span class="token operator"><<</span> <span class="token function">asctime</span><span class="token punctuation">(</span><span class="token function">localtime</span><span class="token punctuation">(</span><span class="token operator">&</span>rawtime<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
Mat cameraMatrix <span class="token operator">=</span> <span class="token punctuation">(</span>
Mat_<span class="token operator"><</span><span class="token keyword">double</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">)</span>
<span class="token operator"><<</span> <span class="token number">1000</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">320</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">,</span> <span class="token number">240</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
Mat distCoeffs <span class="token operator">=</span> <span class="token punctuation">(</span>
Mat_<span class="token operator"><</span><span class="token keyword">double</span><span class="token operator">></span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">,</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token operator"><<</span> <span class="token number">0.1</span><span class="token punctuation">,</span> <span class="token number">0.01</span><span class="token punctuation">,</span> <span class="token operator">-</span><span class="token number">0.001</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">0</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>
fs <span class="token operator"><<</span> <span class="token string">"cameraMatrix"</span> <span class="token operator"><<</span> cameraMatrix <span class="token operator"><<</span> <span class="token string">"distCoffes"</span> <span class="token operator"><<</span> distCoeffs<span class="token punctuation">;</span>
fs <span class="token operator"><<</span> <span class="token string">"features"</span> <span class="token operator"><<</span> <span class="token string">"["</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token number">3</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
<span class="token keyword">int</span> x <span class="token operator">=</span> <span class="token function">rand</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">640</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> y <span class="token operator">=</span> <span class="token function">rand</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">480</span><span class="token punctuation">;</span>
uchar lbp <span class="token operator">=</span> <span class="token function">rand</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token number">256</span><span class="token punctuation">;</span>
fs <span class="token operator"><<</span> <span class="token string">"{:"</span> <span class="token operator"><<</span> <span class="token string">"x"</span> <span class="token operator"><<</span> x <span class="token operator"><<</span> <span class="token string">"y"</span> <span class="token operator"><<</span> y <span class="token operator"><<</span> <span class="token string">"lbp"</span> <span class="token operator"><<</span> <span class="token string">"[:"</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator"><</span> <span class="token number">8</span><span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span>
fs <span class="token operator"><<</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>lbp <span class="token operator">>></span> j<span class="token punctuation">)</span> <span class="token operator">&</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
fs <span class="token operator"><<</span> <span class="token string">"]"</span> <span class="token operator"><<</span> <span class="token string">"}"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
fs <span class="token operator"><<</span> <span class="token string">"]"</span><span class="token punctuation">;</span>
fs<span class="token punctuation">.</span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
}
- 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
CmakeLists.txt:
cmake_minimum_required(VERSION 3.14)
project(write_yaml_using_FileStorage)
set(CMAKE_CXX_STANDARD 14)
set(OpenCV_DIR “/opt/ros/kinetic/share/OpenCV-3.3.1-dev”)
message(${
OpenCV_DIR})
find_package( OpenCV 3 REQUIRED )
add_executable(write_yaml_using_FileStorage main.cpp)
target_link_libraries( write_yaml_using_FileStorage ${ OpenCV_LIBS} )
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
程序运行结果如下:
%YAML:1.0
---
frameCount: 5
calibrationDate: "Tue Jul 30 20:48:34 2019\n"
cameraMatrix: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
distCoffes: !!opencv-matrix
rows: 5
cols: 1
dt: d
data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
-1.0000000000000000e-03, 0., 0. ]
features:
- { x:103, y:166, lbp:[ 1, 0, 0, 1, 0, 1, 1, 0 ] }
- { x:115, y:113, lbp:[ 1, 1, 1, 1, 1, 1, 1, 1 ] }
- { x:586, y:12, lbp:[ 1, 0, 0, 1, 0, 1, 0, 0 ] }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
在这个示例代码中,你会注意到有时候mapping或sequence的所有数据在一行,有时候每个元素一行。这并不是自动格式化造成的,而是由于mapping的起始字符"{:“和”}",sequence的起始字符"[:“和”]"的变化造成的。这个特点只对YAML格式的输出有意义,如果输出文件是XML格式,那么这些细微的差别将会被忽略,mapping与sequence的存储将不会有区别。
使用cv::FileStorage读取文件
cv::FileStorage对象在打开之后,既可以用来写入,也可以用来读取。唯一的区别是flag的值为cv::FileStorage::READ。跟写入时一样,也可以用默认构造函数创建一个未打开的FileStorage对象,之后再通过调用cv::FileStorage::open()函数打开。
FileStorage::open(string fileName, int flag);
- 1
一旦文件被打开,接下来便可对其中的数据进行读取,首先需要确定你要访问的数据名
,即FileStorage最顶层的mapping中的关键字,可以通过重载操作符cv::FileStorage::operator获取自己需要的数据。然而,该操作符的返回值并不是你想要的数据,而是一个FileNode对象。
接下里,如果该值是基本数据类型,则可以通过强制类型转换直接读取,如果该数据是一个mapping对象,可以通过重载操作符[ ],并给定所需关键字访问,如果该数据为sequence对象,可以通过重载的[ ]和一个整型参数访问其中的数据,也可以通过cv::FileNodeIterator迭代器进行访问。在完成读取之后,记得调用成员函数cv::FileStorage::release()关闭文件。
cv::FileNode
当成功构建一个cv::FileNode对象后,便可以用它来完成许多工作。如果它直接表示一个实际的对象(或者一个数字或字符串),你就可以直接使用重载操作符cv::FileNode::operator>>(),将它的值加载到对应类型的变量中。
cv::Mat anArray;
myFileStorage["calibrationMatrix"] >> anArray;
- 1
- 2
cv::FileNode对象同样支持直接赋值给一些基本数据类型。
int aNumber;
myFileStorage["someInteger"] >> aNumber;
- 1
- 2
与下面这种方式等价:
int aNumber;
aNumber = (int)myFileStorage["someInteger"];
- 1
- 2
使用迭代器可以完成对FileNode的遍历。给定一个cv::FileNode对象,成员函数cv::FileNode::begin()和cv::FileNode::end()可以分别返回该mapping或sequence的首元素的迭代器和末尾元素的迭代器。该迭代对象可以通过cv::FileNodeIterator::operator*()操作符来进行解引用操作并返回迭代器对应的位置的FileNode对象。这些迭代器支持常见的自增以及自减操作符。
示例:使用cv::FileNode读取test.yaml文件
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(){
cv::FileStorage fs2(“test.yaml”, cv::FileStorage::READ);
<span class="token keyword">int</span> frameCount <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>fs2<span class="token punctuation">[</span><span class="token string">"frameCount"</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
std<span class="token punctuation">:</span><span class="token punctuation">:</span>string date<span class="token punctuation">;</span>
fs2<span class="token punctuation">[</span><span class="token string">"calibrationDate"</span><span class="token punctuation">]</span> <span class="token operator">>></span> date<span class="token punctuation">;</span>
cv<span class="token punctuation">:</span><span class="token punctuation">:</span>Mat cameraMatrix<span class="token punctuation">,</span> distCoeffs2<span class="token punctuation">;</span>
fs2<span class="token punctuation">[</span><span class="token string">"cameraMatrix"</span><span class="token punctuation">]</span> <span class="token operator">>></span> cameraMatrix<span class="token punctuation">;</span>
fs2<span class="token punctuation">[</span><span class="token string">"distCoffes"</span><span class="token punctuation">]</span> <span class="token operator">>></span> distCoeffs2<span class="token punctuation">;</span>
cout <span class="token operator"><<</span> <span class="token string">"frameCount: "</span> <span class="token operator"><<</span> frameCount <span class="token operator"><<</span> endl
<span class="token operator"><<</span> <span class="token string">"calibration date: "</span> <span class="token operator"><<</span> date <span class="token operator"><<</span> endl
<span class="token operator"><<</span> <span class="token string">"camera matrix: "</span> <span class="token operator"><<</span> cameraMatrix <span class="token operator"><<</span> endl
<span class="token operator"><<</span> <span class="token string">"distoration coeffs: "</span> <span class="token operator"><<</span> distCoeffs2 <span class="token operator"><<</span> endl<span class="token punctuation">;</span>
cv<span class="token punctuation">:</span><span class="token punctuation">:</span>FileNode features <span class="token operator">=</span> fs2<span class="token punctuation">[</span><span class="token string">"features"</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
cv<span class="token punctuation">:</span><span class="token punctuation">:</span>FileNodeIterator it <span class="token operator">=</span> features<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> it_end <span class="token operator">=</span> features<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int</span> idx <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
std<span class="token punctuation">:</span><span class="token punctuation">:</span>vector<span class="token operator"><</span>uchar<span class="token operator">></span> lbpval<span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token punctuation">;</span> it <span class="token operator">!=</span> it_end<span class="token punctuation">;</span> <span class="token operator">++</span>it<span class="token punctuation">,</span> <span class="token operator">++</span>idx<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
cout <span class="token operator"><<</span> <span class="token string">"feature #"</span> <span class="token operator"><<</span> idx <span class="token operator"><<</span> <span class="token string">": "</span><span class="token punctuation">;</span>
cout <span class="token operator"><<</span> <span class="token string">"x="</span> <span class="token operator"><<</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token operator">*</span>it<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token string">"x"</span><span class="token punctuation">]</span> <span class="token operator"><<</span> <span class="token string">", y="</span> <span class="token operator"><<</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token operator">*</span>it<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token string">"y"</span><span class="token punctuation">]</span> <span class="token operator"><<</span> <span class="token string">", lbp: ("</span><span class="token punctuation">;</span>
<span class="token punctuation">(</span><span class="token operator">*</span>it<span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token string">"lbp"</span><span class="token punctuation">]</span> <span class="token operator">>></span> lbpval<span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>lbpval<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span>
cout <span class="token operator"><<</span> <span class="token string">" "</span> <span class="token operator"><<</span> <span class="token punctuation">(</span><span class="token keyword">int</span><span class="token punctuation">)</span>lbpval<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span>
cout <span class="token operator"><<</span> <span class="token string">")"</span> <span class="token operator"><<</span> endl<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
fs2<span class="token punctuation">.</span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 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
程序运行结果如下:
参考
《学习OpenCV 3》(中文版)