opencv:借助xml/yaml存取数据

一遍文章笔记

保存数据的意义

需要保存数据的场景很多。有些数据不只是在运行时查看,经常还需要对其进行后处理。对于一些含有预设参数的配置的文件,必须便捷的进行的读取和写入。opencv提供的FileStorage类等可以方便的完成这些操作。大部分情况下,相对于整个工程而言,读写一些小型的数据文件,并没有什么太大的价值,在已经用到opencv的情况下,并没有必要专门用其他库去实现数据的存取。

opencv存取数据相关的数据结构

cv::FileStorage , cv::FileNode cv::FileNodeIterator。

简介

本文的目的是达成以下要求。

  1. 了解opencv如何存取xml/yaml的数据。 本文先分开介绍,最后给出所有相关c++代码,阅读时可按需取用,不用在乎行文结构。

细节介绍

1. 打开关闭xml/yaml文件

使用构造函数或者open()函数打开文件。

 
  

FileStorage fs(filename, FileStorage::WRITE); // or: // FileStorage fs; // fs.open(filename, FileStorage::WRITE);

在FileStorage对象析构时,文件会自动关闭。但是仍需要显示调用release()

 
  

fs.release()

2. 存取数据

2.1 直接使用的数据存取方式

opencv的FileStorage 支持存取两种类型的数据。以映射的方式存储(类似std::map和python中的字典)、以元素序列方式存储。他们的存取方式有点区别。

以映射的方式存储数据

 
  

//存整数 fs << "iterationNr" << 100; //存opencv格式的矩阵 Mat R = Mat_::eye(3, 3), T = Mat_::zeros(3, 1); fs << "R" << R; // cv::Mat fs << "T" << T;

读取数据。

 
  

//以FileStorage方式打开文件后 int itNr; //fs["iterationNr"] >> itNr; itNr = (int) fs["iterationNr"]; // 取矩阵 fs["R"] >> R; // Read cv::Mat fs["T"] >> T;

序列的存取要复杂一点 以序列的方式存储数据

 
  

//存储一个字符串序列。在元素开头多写入了"[" 结尾多写入了"]" fs << "strings" << "["; // text - string sequence fs << "image1.jpg" << "Awesomeness" << "../data/baboon.jpg"; fs << "]"; // close sequence //存储一个映射的序列。不同之处时用 "{" "}"包裹的 fs << "Mapping"; // text - mapping fs << "{" << "One" << 1; fs << "Two" << 2 << "}";

读取序列数据

 
  

//读取时依赖 cv::FileNode 和 cv::FileNodeIterator 数据结构 FileNode n = fs["strings"]; // Read string sequence - Get node if (n.type() != FileNode::SEQ) { cerr << "strings is not a sequence! FAIL" << endl; return 1; } FileNodeIterator it = n.begin(), it_end = n.end(); // Go through the node for (; it != it_end; ++it) cout << (string)*it << endl; //mapping序列则相对清除的多。 n = fs["Mapping"]; // Read mappings from a sequence cout << "Two " << (int)(n["Two"]) << "; "; cout << "One " << (int)(n["One"]) << endl << endl;

2.2 使用opencv存取自己的数据结构

存取自己的数据结构,在特定情况下,更具有现实意义 举个例子,自定义一个数据结构

 
  

class MyData { public: MyData() : A(0), X(0), id() {} public: // Data Members int A; double X; string id; };

为了让opencv能够读取自定义类型,需要给上面的数据结构添加下面两个函数

 
  

//下面这两个函数,需要添加为上面自定义数据结构的一部分。 void write(FileStorage& fs) const //Write serialization for this class { fs << "{" << "A" << A << "X" << X << "id" << id << "}"; } void read(const FileNode& node) //Read serialization for this class { A = (int)node["A"]; X = (double)node["X"]; id = (string)node["id"]; }

需要在自定义结构的外面加上下面两个函数

 
  

static void write(FileStorage& fs, const std::string&, const MyData& x) { x.write(fs); } static void read(const FileNode& node, MyData& x, const MyData& default_value = MyData()){ if(node.empty()) x = default_value;//如果node为空,就返回一个默认的结果 else x.read(node); }

添加完上面四个函数后,就可以用opencv读取上面的自定义数据结构了 例子代码如下

 
  

MyData m(1); fs << "MyData" << m; // your own data structures fs["MyData"] >> m;

上述代码,当读取一个不存在的节点时,将输出指定数据结构的默认结果

 
  

std::cout << "Attempt to read NonExisting (should initialize the data structure with its default)."; fs["NonExisting"] >> m; std::cout << std::endl << "NonExisting = " << std::endl << m << std::endl;

关于opencv如何存取xml/yaml的数据。就这么多了。

你可能感兴趣的:(opencv4,opencv3-0,opencv,python,计算机视觉)