xml 是Extensible Markup Language可扩展标记语言的简写;
本文主要介绍:
xml文件结构;
xml文件的读和写;
xml文件中-vector数据结构;
xml文件中-map数据结构;
遍历xml文件节点;
xml中自定义结构存储;
1. xml文件结构
①xml文件的第一行为xml文件说明,一般说明了xml的版本和编码信息;
如:
<? xmlversion="1.0" encoding="UTF-8"?>
②xml文件的第二行为xml的起始节点,也是根节点;
Opencv的xml文件默认的根节点为:
<opencv_storage>……</opencv_storage>
③每个xml文件有且只有一个根节点,其他节点都包含在这个根节点之内,每个节点又可以包含若干个子节点。
2. xml文件的读和写
2.1 向xml文件的写数据
首先用可写的方式打开一个test.xml文件,
然后写入一个Mat矩阵,
最后关闭。
2.2 从xml文件的读数据
首先用可读方式打开一个test.xml文件,
然后读出“src1”节点里面的中间,
最后关闭。
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\core\core.hpp>
using namespace std;
using namespace cv;
int main()
{
//========建立节点(写数据)=========
Mat src=(Mat_<double>(3,3)<<1,2,3,4,5,6,7,8,9);
FileStorage fswrite("stereo.xml",FileStorage::WRITE);
fswrite<<"src1"<<src;
fswrite.release();
cout<<"Write Finished"<<endl;
//========遍历节点(读数据)=========
FileStorage fsread("stereo.xml",FileStorage::READ);
Mat dst;
fsread["src1"]>>dst;
cout<<dst<<endl;
fsread.release();
cout<<"Read Finished"<<endl;
getchar();
return 0;
}
2.3 读和写打开xml文件也可以和下面那样:
FileStorage fswrite;
fswrite.open("stereo.xml",FileStorage::WRITE);
FileStorage fsread;
fsread.open("stereo.xml",FileStorage::READ);
【注】:FileStorage::WRITE每次都会新建一个文件,如果文件已经存在就会被覆盖掉,如果不想被覆盖,而是继续在已有的文件基础上添加内容,那么可以以FileStorage::APPEND的方式来打开!
3 xml文件中-vector数据结构
vector数据,xml文件节点,不包含子节点;
在输入vector数据的开始和结尾要分别输入“[”,“]”;
【注】:在输入vector数据前要先输入标签名称;
4 xml文件中-map数据结构
map数据,xml文件节点,包含子节点;
在输入map数据的开始和结尾要分别写入“{”,“}”,
【注】:在输入 map数据前要先输入标签名称;
示例:
手动创建一个xml父节点(map),包含三个子节点(vector)。
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\core\core.hpp>
using namespace std;
using namespace cv;
int main()
{
//========建立节点(写数据)=========
FileStorage fswrite;
fswrite.open("calib.xml",FileStorage::WRITE);
fswrite<<"src"<<"{"<<"src1"<<"["<<1<<2<<3<<"]"//子节点
<<"src2"<<"["<<1<<2<<3<<"]"
<<"src3"<<"["<<1<<2<<3<<"]"<<"}";
fswrite.release();
cout<<"Write Finished"<<endl;
getchar();
return 0;
}
产生的xml文件如下:
5 遍历xml文件节点:
在包含多个节点的xml文件中,
遍历的时候,
首先先获取了文件的根节点-FileNode;
然后定义一个迭代器-FileNodeIterator,
从根节点的第一个节点开始遍历,直到最后一个节点结束。
结果分析:
下面是stereo.xml的内容,
其中<?xml version="1.0"?>为文件信息,说明了xml的版本为1.0;<opencv_storage>...</opencv_storage>为根节点,
<src1 type_id="opencv-matrix">...</src1>为第一级节点(根节点的子节点),<rows>3</rows>为第二级节点,它是<src1 type_id="opencv-matrix">...</src1>的子节点。
6、xml中自定义结构存储:
OpenCV的xml可以实现int,float,double,string,mat等数据类型的存储和读取;
但是往往我们会自定义类型的数据,那么如何实现自定义数据的存取?
有如下步骤:
①自定义数据结构:
②定义完数据结构后需要重载两个函数;
③对自定义的数据进行存储和读取;
如:
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\features2d\features2d.hpp>
#include <opencv2\core\core.hpp>
using namespace std;
using namespace cv;
class faceInfo
{
public:
//写入数据【1】
void write(FileStorage& fs) const
{
fs<<"{"<<"matrix"<<matrix<<"label"<<label<<"}";
}
//读出数据【2】
void read(const FileNode& node)
{
node["matrix"]>>matrix;
node["label"]>>label;
}
public:
Mat matrix;
string label;
};
//由操作符“<<”调用【3】
void write(FileStorage& fs, const string&, const faceInfo& x)
{
x.write(fs);
}
//由操作符“>>”调用【4】
void read(const FileNode& node, faceInfo& x, const faceInfo& default_value = faceInfo())
{
if(node.empty())
x = default_value;
else
x.read(node);
}
int main()
{
//========建立节点(写数据)=========
Mat src=(Mat_<double>(3,3)<<1,2,3,4,5,6,7,8,9);
faceInfo face1={src,"Jack"};//faceInfo为自定义类
faceInfo face2={src,"John"};
faceInfo face3={src,"Mike"};
FileStorage fswrite("calib.xml",FileStorage::WRITE);
fswrite<<"face1"<<face1<<"face2"<<face2<<"face3"<<face3;
fswrite.release();
cout<<"Write Finished"<<endl;
//========遍历节点(读数据)=========
FileStorage fsread("calib.xml",FileStorage::READ);
FileNode rootnode=fsread.root();//获取根节点
if(rootnode.type()!=FileNode::MAP){
cout<<"This is not map !"<<endl;
}
FileNodeIterator it=rootnode.begin();
while(it<rootnode.end())
{
faceInfo dst;
it>>dst;
//(*it)>>dst;//不行
cout<<dst.label<<endl;
cout<<dst.matrix<<endl;
}
cout<<"Reaed Finished"<<endl;
fsread.release();
getchar();
return 0;
}
/// 从xml文件中读取Mat类型数据
/// \param inputFile 文件名
/// \param nodeName 子节点明
/// \param outMatrix Mat类型数据
/// \return 返回结果
bool readMatrixFromXml(string inputFile, string nodeName, Mat &outMatrix)
{
FileStorage fsread(inputFile, FileStorage::READ);
if (!fsread.isOpened())
{
return false;
}
fsread[nodeName] >> outMatrix;
if (outMatrix.empty())
{
return false;
}
fsread.release();
return true;
}
参考文章:
1. https://jingyan.baidu.com/article/22a299b5f4d07e9e18376a7f.html