1、XML和YAML文件简介
XML文件是一种元标记语言,即开发者可以根据自身需要定义自己的标记。它是一种语义和结构语言,描述了文档的语义和结构。
YAML以数据为中心,是一个可读性高,用来表达资料序列的格式。.yml和.yaml为YAML文件的后缀名。
YAML试图用一种比XML更敏捷的方式来完成XML所完成的任务。
2、FileStorage类操作文件
一般使用如下过程来写入或者读取数据到XML或YAML文件中
(1)实例化一个FileStorage类的对象,用默认带参数的构造函数完成初始化,或者用FileStorage::open()成员函数辅助初始化
(2)使用流操作符<<进行文件写入操作,或者>>进行文件读取操作
(3)使用FileStorage::release()函数析构掉FileStorage类对象,同时关闭文件
下边对2中三个步骤进行示例讲解
【第一步】XML、YAML文件的打开
(1)准备文件写操作
FileStorage是OpenCV中XML和YAML文件的存储类,封装了所有相关的信息。是OpenCV从文件中读取数据或向文件中写入数据时必须要使用的一个类。
构造函数为FileStorage::FIleStorage,有两个重载:
FIleStorage::FileStorage()
FIleStorage::FileStorage(const string& source, int flags, const string& encoding=string())
对于第一种不带参数的构造函数,可以使用成员函数FileStorage::open进行数据写操作:
FileStorage fs;
fs.open("abc.xml", FileStorage::WRITE);
对于第二种带参数的构造函数,进行写操作:
fs.open("abc.xml", FileStorage::WRITE);
(2)准备文件读操作
采用FileStorage::READ标识符进行读操作:
第一种方式:
fs.open("abc.xml", FileStorage::READ);
第二种方式:
FileStorage fs;
fs.open("abc.xml", FileStorage::READ);
上边操作是以XML文件为例子的,对于YAML文件同样适用。
【第二步】进行文件读写操作
(1)文本和数字的输入和输出
定义好FileStorage类对象之后,写入文件可以使用“<<”运算符,如
fs<<“iterationNr”<<100
读取文件,使用“>>”运算符,如:
int inNr;
fs["iterationNr"]>>itNr;
itNr = (int)fs["iterationNr"];
(2)OpenCV数据结构的输入和输出
OpenCV数据结构的输入和输出和基本的C++形式相同,如:
//手数据结构的初始化
Mat R = Mat_<uchar>::eye(3, 3);
Mat T = Mat_<double>::zeros(3, 1);
//向Mat中写入数据
fs << "R" << R;
fs << "T" << T;
//从Mat中读取数据
fs["R"] >> R;
fs["T"] >> T;
【第三步】vector(arrays)和maps的输入和输出
对于vector结构的输入和输出,注意需要在一个元素前加上“[”,在最后一个元素前加上“]”,如:
fs << "string" << "["; //开始读入string文本序列
fs << "imagel.jpg" << "Awesomeness" << "baboon.jpg";
fs << "]"; //关闭序列
对于maps结构的操作,使用的符号是“{”和“}”,如:
fs << "mapping"; //开始读入mapping文本
fs << "{" << "One" << 1;
fs << "Two" << 2 << "}";
读取这些结构时,会用到FileNode和FileNodeIterator数据结构。FileStorage类的“[”、“]”操作符会返回FileNode数据类型;对于一连串的node,可以使用FileNoelIterator结构,如:
FileNode n = fs["strings"]; // 读取字符串序列以得到节点
if(n.type() != FileNode::SEQ)
{
cerr << "发生错误!字符串不是一个序列!" << endl;
return 1;
}
FileNodeIterator it = n.begin(), it_end = n.end(); //遍历节点
for(; it != it_end; ++it)
cout << (string)*it << endl;
【第四部】文件关闭
文件关闭会在FileStorage类销毁时自动关闭,但也可显示调用其析构函数FileStorage::release()实现。
析构函数FileStorage::release()会析构掉FileStorage类对象,同时关闭文件。
调用过程:
fs.release();
示例程序
【1】示例程序:XML和YAML文件的写入
//---------------------------------【头文件、命名空间包含部分】-------------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include "opencv2/opencv.hpp"
#include <time.h>
using namespace cv;
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main()
{
//初始化
FileStorage fs("test.yaml", FileStorage::WRITE);
//开始文件写入
fs << "frameCount" << 5;
time_t rawtime; time(&rawtime);
fs << "calibrationDate" << asctime(localtime(&rawtime)); //写入当前系统时间
Mat cameraMatrix = (Mat_<double>(3, 3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
Mat distCoeffs = (Mat_<double>(5, 1) << 0.1, 0.01, -0.001, 0, 0);
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
fs << "features" << "[";
for (int i = 0; i < 3; i++)
{
int x = rand() % 640;
int y = rand() % 480;
uchar lbp = rand() % 256;
fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
for (int j = 0; j < 8; j++)
fs << ((lbp >> j) & 1);
fs << "]" << "}";
}
fs << "]";
fs.release();
printf("\n文件读写完毕,请在工程目录下查看生成的文件~");
getchar();
return 0;
}
运行结果为:
【2】示例程序:XML和YAML文件的读取
//---------------------------------【头文件、命名空间包含部分】-------------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include "opencv2/opencv.hpp"
#include <time.h>
# include <string>
using namespace cv;
using namespace std;
int main()
{
//初始化
FileStorage fs2("test.yaml", FileStorage::READ);
// 第一种方法,对FileNode操作
int frameCount = (int)fs2["frameCount"];
string date;
// 第二种方法,使用FileNode运算符> >
fs2["calibrationDate"] >> date;
Mat cameraMatrix2, distCoeffs2;
fs2["cameraMatrix"] >> cameraMatrix2;
fs2["distCoeffs"] >> distCoeffs2;
cout << "frameCount: " << frameCount << endl
<< "calibration date: " << date << endl
<< "camera matrix: " << cameraMatrix2 << endl
<< "distortion coeffs: " << distCoeffs2 << endl;
FileNode features = fs2["features"];
FileNodeIterator it = features.begin(), it_end = features.end();
int idx = 0;
vector<uchar> lbpval;
//使用FileNodeIterator遍历序列
for (; it != it_end; ++it, idx++)
{
cout << "feature #" << idx << ": ";
cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
// 我们也可以使用使用filenode > > std::vector操作符很容易的读数值阵列
(*it)["lbp"] >> lbpval;
for (int i = 0; i < (int)lbpval.size(); i++)
cout << " " << (int)lbpval[i];
cout << ")" << endl;
}
fs2.release();
//程序结束,输出一些帮助文字
printf("\n文件读取完毕,请输入任意键结束程序~");
getchar();
return 0;
}
运行结果为: