xml 是Extensible Markup Language可扩展标记语言的简写;

本文主要介绍:

xml文件结构;

xml文件的读和写;

xml文件中-vector数据结构;

xml文件中-map数据结构;

遍历xml文件节点;

xml中自定义结构存储;

opencv批量读入文件 opencv读取xml文件_opencv批量读入文件

1. xml文件结构

xml文件的第一行为xml文件说明,一般说明了xml的版本和编码信息

如:

<? xmlversion="1.0" encoding="UTF-8"?>

xml文件的第二行为xml的起始节点,也是根节点

Opencv的xml文件默认的根节点为:

<opencv_storage>……</opencv_storage>

每个xml文件有且只有一个根节点,其他节点都包含在这个根节点之内,每个节点又可以包含若干个子节点

opencv批量读入文件 opencv读取xml文件_数据_02

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的方式来打开!

opencv批量读入文件 opencv读取xml文件_数据_03

3 xml文件中-vector数据结构

vector数据,xml文件节点,不包含子节点;

在输入vector数据的开始和结尾要分别输入“[”,“]”;

【注】:在输入vector数据前要先输入标签名称;

opencv批量读入文件 opencv读取xml文件_xml_04

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文件如下:

opencv批量读入文件 opencv读取xml文件_数据_05

5 遍历xml文件节点:

在包含多个节点的xml文件中,

遍历的时候,

首先先获取了文件的根节点-FileNode;

然后定义一个迭代器-FileNodeIterator,

从根节点的第一个节点开始遍历,直到最后一个节点结束。  

opencv批量读入文件 opencv读取xml文件_数据_06

结果分析:

下面是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>的子节点。

opencv批量读入文件 opencv读取xml文件_数据_07

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;

}

opencv批量读入文件 opencv读取xml文件_xml文件_08

opencv批量读入文件 opencv读取xml文件_数据_09

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