【opencv】示例-filestorage.cpp 使用 FileStorage 类进行序列化与反序列化的示例

终端输出:

properties 复制代码
writing images
image1.jpg myfi.png baboon.jpg
writing mats
R = [1, 0, 0;
 0, 1, 0;
 0, 0, 1]
T = [0;
 0;
 0]
writing MyData struct
{ id = mydata1234, X = 3.14159, A = 97}
reading images
image1.jpg
myfi.png
baboon.jpg
reading R and T
R = [1, 0, 0;
 0, 1, 0;
 0, 0, 1]
T = [0;
 0;
 0]
read mdata
{ id = mydata1234, X = 3.14159, A = 97}
attempting to read mdata_b
read mdata_b
{ id = , X = 0, A = 0}
Try opening input.yml to see the serialized data.


Read data from string
attempting to read mdata_b from string
read mdata
{ id = mydata1234, X = 3.14159, A = 97}
Write data to string
writing MyData struct
{ id = mydata1234, X = 3.14159, A = 97}
Created string:
%YAML:1.0
---
mdata:
   A: 97
   X: 3.1415926535897931e+00
   id: mydata1234
objectivec 复制代码
```cpp
/*
 * 文件存储示例 filestorage_sample 演示了 OpenCV 序列化功能的用法
 */


#include "opencv2/core.hpp"   // 包含核心 OpenCV 库文件
#include <iostream>           // 包含标准输入输出流库
#include <string>             // 包含字符串相关库


// 使用命名空间中的元素,避免每次都需要 std::前缀
using std::string;
using std::cout;
using std::endl;
using std::cerr;
using std::ostream;
using namespace cv;           // 使用 OpenCV 命名空间


// 帮助函数,说明程序如何使用
static void help(char** av)
{
  // 输出帮助信息
  cout << "\nfilestorage_sample 演示了 OpenCV 序列化功能的用法。\n"
      << "使用方法:\n"
      <<  av[0] << " outputfile.yml.gz\n"
      << "\n   上面的 outputfile 可以有多种不同的扩展名,见下文。"
      << "\n该程序演示了在 OpenCV 中使用 FileStorage 进行序列化,即使用 << 和 >> 操作符\n"
      << "例如,如何创建一个类并让它实现序列化,以及如何使用它来读写矩阵。\n"
      << "FileStorage 允许你将数据序列化为由文件扩展名指定的不同格式。"
          << "\n你应该尝试使用不同的文件扩展名。(如 yaml yml xml xml.gz yaml.gz 等)\n" << endl;
}


// 自定义的数据结构
struct MyData
{
  // 默认构造函数
  MyData() :
    A(0), X(0), id()
  {
  }
  // 带参数的构造函数
  explicit MyData(int) :
    A(97), X(CV_PI), id("mydata1234")
  {
  }
  // 成员变量
  int A;      // 整型
  double X;   // 双精度型
  string id;  // 字符串类型
  // 成员函数,写入序列化数据
  void write(FileStorage& fs) const // 为该类编写序列化
  {
    fs << "{" << "A" << A << "X" << X << "id" << id << "}";
  }
  // 成员函数,读取序列化数据
  void read(const FileNode& node)  // 为该类读取序列化
  {
    // 读取节点数据并赋予成员变量
    A = (int)node["A"];
    X = (double)node["X"];
    id = (string)node["id"];
  }
};


// 需要存在这些 read 和 write 函数,如 operations.hpp 中的内联函数
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;
  else
    x.read(node);
}


// 重载输出操作符,以便于输出 MyData 结构
static ostream& operator<<(ostream& out, const MyData& m){
  out << "{ id = " << m.id << ", ";
  out << "X = " << m.X << ", ";
  out << "A = " << m.A << "}";
  return out;
}


// 主函数
int main(int ac, char** av)
{
  // 解析命令行参数
  cv::CommandLineParser parser(ac, av,
    "{@input||}{help h ||}"
  );
  if (parser.has("help"))
  {
    help(av);
    return 0;
  }
  // 获取输入文件名
  string filename = parser.get<string>("@input");
  if (filename.empty())
  {
    help(av);
    return 1;
  }


  // 写入数据
  {
    FileStorage fs(filename, FileStorage::WRITE);


    cout << "writing images\n";
    fs << "images" << "[";


    // 写入图像文件名
    fs << "image1.jpg" << "myfi.png" << "baboon.jpg";
    cout << "image1.jpg" << " myfi.png" << " baboon.jpg" << endl;


    // 结束数组输入
    fs << "]";


    cout << "writing mats\n";
    // 创建矩阵并初始化
    Mat R =Mat_<double>::eye(3, 3),T = Mat_<double>::zeros(3, 1);
    // 输出矩阵信息
    cout << "R = " << R << "\n";
    cout << "T = " << T << "\n";
    // 写入矩阵
    fs << "R" << R;
    fs << "T" << T;


    cout << "writing MyData struct\n";
    // 创建自定义结构并序列化
    MyData m(1);
    fs << "mdata" << m;
    cout << m << endl;
  }


  // 读取数据
  {
    FileStorage fs(filename, FileStorage::READ);


    if (!fs.isOpened())
    {
      cerr << "failed to open " << filename << endl;
      help(av);
      return 1;
    }


    FileNode n = fs["images"];
    if (n.type() != FileNode::SEQ)
    {
      cerr << "images is not a sequence! FAIL" << endl;
      return 1;
    }


    cout << "reading images\n";
    // 迭代读取图像文件名
    FileNodeIterator it = n.begin(), it_end = n.end();
    for (; it != it_end; ++it)
    {
      cout << (string)*it << "\n";
    }


    Mat R, T;
    cout << "reading R and T" << endl;


    // 读取矩阵 R 和 T
    fs["R"] >> R;
    fs["T"] >> T;


    // 输出矩阵信息
    cout << "R = " << R << "\n";
    cout << "T = " << T << endl;


    // 创建自定义结构并读取序列化数据
    MyData m;
    fs["mdata"] >> m;


    cout << "read mdata\n";
    cout << m << endl;


    cout << "attempting to read mdata_b\n";   // 展示空矩阵的默认行为
    fs["mdata_b"] >> m;
    cout << "read mdata_b\n";
    cout << m << endl;


  }


  // 提醒用户可以打开文件看序列化的数据
  cout << "Try opening " << filename << " to see the serialized data." << endl << endl;


  // 从字符串读取
  {
    cout << "Read data from string\n";
    // 创建一个包含数据的字符串
    string dataString =
        "%YAML:1.0\n"
        "mdata:\n"
        "   A: 97\n"
        "   X: 3.1415926535897931e+00\n"
        "   id: mydata1234\n";
    // 创建自定义结构并读取字符串中的序列化数据
    MyData m;
    FileStorage fs(dataString, FileStorage::READ | FileStorage::MEMORY);
    cout << "attempting to read mdata_b from string\n";   // 展示空矩阵的默认行为
    fs["mdata"] >> m;
    cout << "read mdata\n";
    cout << m << endl;
  }


  // 写入到字符串
  {
    cout << "Write data to string\n";
    // 创建文件存储,指定操作内存和 YAML 格式
    FileStorage fs(filename, FileStorage::WRITE | FileStorage::MEMORY | FileStorage::FORMAT_YAML);


    cout << "writing MyData struct\n";
    // 创建自定义数据并序列化
    MyData m(1);
    fs << "mdata" << m;
    cout << m << endl;
    // 释放文件存储并获取字符串
    string createdString = fs.releaseAndGetString();
    cout << "Created string:\n" << createdString << "\n";
  }


  return 0;
}

这段代码是一个演示如何使用 OpenCV 中 FileStorage 类进行序列化与反序列化的示例。代码首先定义了一个自定义数据结构 MyData,它具有序列化和反序列化的方法。在 main 函数中,程序首先处理输入的文件名,然后展示如何将图片名称、矩阵和自定义的 MyData 结构写入一个文件。随后,程序演示如何从该文件读取这些数据。此外,也演示了如何将数据序列化为字符串以及如何从字符串反序列化数据。该代码结合了命令行参数解析、文件读写、自定义结构与数据类型的序列化/反序列化,以及错误处理。这是学习 OpenCV 数据持久化一个非常实用的例子。

相关推荐
excel3 分钟前
前端必备:从能力检测到 UA-CH,浏览器客户端检测的完整指南
前端
前端小巷子9 分钟前
Vue 3全面提速剖析
前端·vue.js·面试
cwn_15 分钟前
牛津大学xDeepMind 自然语言处理(1)
人工智能·深度学习·机器学习·自然语言处理
悟空聊架构16 分钟前
我的网站被攻击了,被干掉了 120G 流量,还在持续攻击中...
java·前端·架构
CodeSheep17 分钟前
国内 IT 公司时薪排行榜。
前端·后端·程序员
尖椒土豆sss21 分钟前
踩坑vue项目中使用 iframe 嵌套子系统无法登录,不报错问题!
前端·vue.js
遗悲风22 分钟前
html二次作业
前端·html
前端双越老师22 分钟前
【干货】使用 langChian.js 实现掘金“智能总结” 考虑大文档和 token 限制
人工智能·langchain·node.js
江城开朗的豌豆26 分钟前
React输入框优化:如何精准获取用户输入完成后的最终值?
前端·javascript·全栈
CF14年老兵26 分钟前
从卡顿到飞驰:我是如何用WebAssembly引爆React性能的
前端·react.js·trae