OpenCV2笔记-XML/YAML持久化

XML/YAML文件存储器。写到一个文件存储器。

你能存储各种OpenCV数据结构到XML/YAML格式的文件中或者从中恢复数据。也能存储和加载任意的复杂的数据结构,包括OpenCV数据结构,原始的数据类型(整形、浮点数和文本串)。

写数据到XML/YAML文件的步骤:

  1. 创建一个FileStorage对象,打开对象并写数据。使用带个文件名构造函数FileStorage::FileStorage(),或者使用默认的构造函数,然后使用open函数打开文件。文件格式取决于使用的文件名的后缀(“.xml”、“.yaml”、“.yml”)。
  2. 像STL流一样使用<<写入数据。
  3. 调用release函数关闭文件。或者FileStorage析构函数也会关闭文件。

例子:

#include <opencv2/opencv.hpp>

#include <time.h>



using namespace cv;





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();

    return 0;

}

上面这个例子存储数据到yml,整形,文本串(标准时间),2个矩阵,一个包含特征坐标和lbp值的自定义结构“features”。

例子的输出如下:

%YAML:1.0

frameCount: 5

calibrationDate: "Fri Jun 17 14:09:29 2011\n"

cameraMatrix: !!opencv-matrix

   rows: 3

   cols: 3

   dt: d

   data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]

distCoeffs: !!opencv-matrix

   rows: 5

   cols: 1

   dt: d

   data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,

       -1.0000000000000000e-03, 0., 0. ]

features:

   - { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] }

   - { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] }

   - { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] }

作为一个练习,你可以使用“.yaml”或者“.xml”替换上面的文件的扩展名。

对于代码和程序的输出,需要注意几点:

  • 产生的yaml或者xml可以使用多种的集合嵌套。这里有2种:命名的集合(映射)和未命名的集合(序列)。在映射中,每个元素都一个name,使用name存取元素。与C/C++中的STL的map容器和python中的字典比较像。序列中,元素没有name,通过索引访问元素。与C/C++中的数组和vector容器或者python的列表和元组比较像。多样性指的是单个集合中的元素可以拥有不同的类型。在yaml/yml中,顶级的集合是映射。opencv中的矩阵存储成映射,而对于矩阵中的元素为序列。
  • 当写映射时,先写入元素name,然后是元素值。当写入序列时,只需要一个接着一个写入元素即可。跟C的数据结构一样,opencv数据结构(比如cv::Mat)使用<<写入文件。
  • 写入映射时,必须先写入特殊的字符串“{”,接着是元素name和元素值,然后是特殊字符串“}”。
  • 写入序列时,必须先写入特殊的字符串“[”,接着是元素值,然后是特殊字符串“]”。
  • 在yaml(不是xml)中,映射和序列能像python的内联的形式写入文件。使用“{:”和“[:”代替“{”和“[”。对应xml,“:”将被忽略。

opencv_source_code/samples/cpp/filestorage.cpp-是一个完整的例子。

从文件存储器中读取数据

 读取先前写入到xml或者yaml文件的数据的步骤:

  1. 使用FileStorage::FileStorage()构造函数或者FileStorage::open()函数打开文件存储器。OpenCV当前的实现是解析整个文件,然后在内存中文件存储器表示为层次的文件节点。
  2. 使用FileStorage::operator[]()、FileNode::operator[]()和FileNodeIterator读取数据。
  3. 使用FileStorage::release()关闭文件存储器。

例子:

#include <opencv2/opencv.hpp>

#include <time.h>

#include <string>

#include <iostream>



using namespace cv;

using namespace std;





int main()

{

    FileStorage fs("test.yaml", FileStorage::READ);



    int frameCount = (int)fs["frameCount"];

    std::string date;

    fs["calibrationDate"] >> date;

    Mat cameraMatrix, distCoeffs;

    fs["cameraMatrix"] >> cameraMatrix;

    fs["distCoeffs"] >> distCoeffs;

    cout << "frameCount: " << frameCount << endl;

    cout << "calibrationDate: " << date << endl;

    cout << "cameraMatrix: " << cameraMatrix << endl;

    cout << "distCoeffs: " << distCoeffs << endl;



    FileNode features = fs["features"];

    FileNodeIterator it = features.begin(), it_end = features.end();

    int idx = 0;

    std::vector<uchar> lbpval;

    for (; it != it_end; ++it, ++idx)

    {

        cout << "feature #" << idx << ": ";

        cout << "x=" << (int)(*it)["x"] << ",, y=" << (int)(*it)["y"] << ", lbp: (";

        (*it)["lbp"] >> lbpval;

        for(int i = 0; i < (int)lbpval.size(); ++i)

        {

            cout << " " << (int)lbpval[i];

        }

        cout << ")" << endl;

    }



    fs.release();

    return 0;

}

 

你可能感兴趣的:(opencv)