前言

有时候我们处理完图像后需要保存一下数据到文件上,以供下一步的处理。一个比较广泛的需求场景就是:我们对一幅图像进行特征提取之后,需要把特征点信息保存到文件上,以供后面的机器学习分类操作。那么如果遇到这样的场景,我们有什么好方法,搭建这类的小型数据库文件?我第一时间想到的是把这些数据全写到文件上,下次我们需要这些数据就把他们从文件里读出来就好了。

其实更好的办法是使用xml和yml,因为他们更具有可读性,简直就是为保存数据结构而生的好方法!OpenCV提供了很好用的读写xml/yml的类,我们只要掌握其读写要领,很容易就可以实现这个小型数据库。

xml/yml的写操作

如何将我们的数据写入文件保存下来?

一个简单数据写入的例子

下面是我们最常用的一些数据类型的写入xml的操作。

#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>using namespace std;
using namespace cv;typedef struct
{int x;int y;string s;
}test_t;int main(int argc, char** argv)
{FileStorage fs("test.xml", FileStorage::WRITE); //填入写操作//测试数据int a1 = 2;char a2 = -1;string str = "hello sysu!";int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };test_t t = { 3,4,"hi sysu" };map<string, int> m;m["kobe"] = 100;m["james"] = 99;m["curry"] = 98;//写入文件操作,先写标注在写数据fs << "int_data" << a1;fs << "char_data" << a2;fs << "string_data" << str;//写入数组fs <<"array_data"<< "["; //数组开始for (int i = 0; i < 10; i++){fs << arr[i];}fs << "]"; //数组结束//写入结构体fs << "struct_data" << "{"; //结构体开始fs << "x" << t.x;fs << "y" << t.y;fs << "s" << t.s;fs << "}";  //结构结束//map的写入 fs << "map_data" << "{";  //map的开始写入map<string, int>::iterator it = m.begin();for (; it != m.end(); it++){fs << it->first << it->second;}fs << "}";  //map写入结束return 0;
}

打开test.xml文件,我们看到我们的数据保存是这样子的:

如果我们将文件存为test.yml,即

FileStorage fs("test.yml", FileStorage::WRITE);

那么我们最终的得到的test.yml是这样子的:

我们还可以保存为txt格式

FileStorage fs("test.txt", FileStorage::WRITE);

打开看是这样的:

我们还还可以保存为doc文件!

FileStorage fs("test.doc", FileStorage::WRITE); 

打开看是这样子的:

我们可以看出,显然yml文件的排版更加简洁明了,xml文件却显得有点冗余和杂乱了。

一个复杂写入的例子

在这里举一个简易的学生信息系统文件的搭建,以熟悉一下较为复杂的数据结构的写入文件的操作流程。

#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>using namespace std;
using namespace cv;typedef struct
{string phone_num;string address;
}contact_t;typedef struct
{string name;int age;
}parents_t;typedef struct
{string name;int age;int id;contact_t contact_ways;parents_t parents[2];
}student_t;int main(int argc, char** argv)
{FileStorage fs("student.xml", FileStorage::WRITE); //填入写操作student_t st[3]; memset(st, 0, sizeof(st));//测试数据填入st[0].name = "Kobe";st[0].age = 21;st[0].id = 1;st[0].contact_ways.address = "1st building";st[0].contact_ways.phone_num = "123";st[0].parents[0].name = "dad";st[0].parents[1].name = "mum";st[0].parents[0].age = 40;st[0].parents[1].age = 39;st[1].name = "James";st[1].age = 20;st[1].id = 2;st[1].contact_ways.address = "2st building";st[1].contact_ways.phone_num = "12223";st[1].parents[0].name = "daddy";st[1].parents[1].name = "mumy";st[1].parents[0].age = 44;st[1].parents[1].age = 38;fs << "student" << "["; //结构体数组的开始for (int i = 0; i < 3; i++){fs <<"{"; //结构体的开始fs << "name" << st[i].name;fs << "age" << st[i].age;fs << "id" << st[i].id;fs << "contact_ways" << "{";  //嵌套结构体的开始fs << "phone_number" << st[i].contact_ways.phone_num;fs << "address" << st[i].contact_ways.address;fs << "}";  //结构体结束fs << "parents"<<"[";  //嵌套结构体数组开始for (int j = 0; j < 2; j++){fs << "{";fs << "name" << st[i].parents[j].name;fs << "age" << st[i].parents[j].age;fs << "}";}fs << "]";  //嵌套结构体数组结束fs << "}"; //结构体结束}fs << "]"; // 结构体数组结束return 0;
}

打开student.xml文件,如下

<?xml version="1.0"?>
<opencv_storage>
<student><_><name>Kobe</name><age>21</age><id>1</id><contact_ways><phone_number>"123"</phone_number><address>"1st building"</address></contact_ways><parents><_><name>dad</name><age>40</age></_><_><name>mum</name><age>39</age></_></parents></_><_><name>James</name><age>20</age><id>2</id><contact_ways><phone_number>"12223"</phone_number><address>"2st building"</address></contact_ways><parents><_><name>daddy</name><age>44</age></_><_><name>mumy</name><age>38</age></_></parents></_><_><name>""</name><age>0</age><id>0</id><contact_ways><phone_number>""</phone_number><address>""</address></contact_ways><parents><_><name>""</name><age>0</age></_><_><name>""</name><age>0</age></_></parents></_></student>
</opencv_storage>

若存储的是yml文件,打开如下:

%YAML:1.0
student:-name: Kobeage: 21id: 1contact_ways:phone_number: "123"address: "1st building"parents:-name: dadage: 40-name: mumage: 39-name: Jamesage: 20id: 2contact_ways:phone_number: "12223"address: "2st building"parents:-name: daddyage: 44-name: mumyage: 38-name: ""age: 0id: 0contact_ways:phone_number: ""address: ""parents:-name: ""age: 0-name: ""age: 0

xml/yml的读操作

我们的数据已经稳妥地写入文件保存下来了,接下来我们想从该文件中读取出我们的数据,该如何操作呢?我们继续以上述的例子数据为例,讲解读操作。

一个简单读入的例子

我们举个简单例子,读入上面提到test.xml的数据。

#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>using namespace std;
using namespace cv;typedef struct
{int x;int y;string s;
}test_t;int a1;
int a2;
string str;
int arr[10];
test_t t;
map<string, int> m;//打印出学生资料,来验证读取文件信息是否成功
void data_info_dump()
{cout << "a1:" << a1 << endl;cout << "a2:" << a2 << endl;cout << "str:" << str << endl;cout << "t.x:" << t.x << endl;cout << "t.y:" << t.y << endl;cout << "t.s:" << t.s << endl;cout << "curry:" << m["curry"] << endl;cout << "kobe:" << m["kobe"] << endl;cout << "james:" << m["james"] << endl;for (int i = 0; i < 10; i++){cout << arr[i] << endl;}
}int main(int argc, char** argv)
{FileStorage fs("test.xml", FileStorage::READ); //填入读操作a1 = (int)fs["int_data"];a2 = (int)fs["char_data"];str = (string)fs["string_data"];//读入数组FileNode arr_node = fs["array_data"];FileNodeIterator fni = arr_node.begin(); FileNodeIterator fniEnd = arr_node.end();int count = 0;for (; fni != fniEnd; fni++){arr[count++] = (int)(*fni);}//读入mapFileNode map_node = fs["map_data"];m["curry"] = (int)map_node["curry"];m["james"] = (int)map_node["james"];m["kobe"] = (int)map_node["kobe"];//读入结构体FileNode struct_node = fs["struct_data"];t.x = (int)struct_node["x"];t.y = (int)struct_node["y"];t.s = (string)struct_node["s"];data_info_dump();return 0;
}

打印如下:

一个复杂读入的例子

我们以读取上面所提到的student.xml为例,说明如何读取一个xml文件数据到内存。

#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>using namespace std;
using namespace cv;typedef struct
{string phone_num;string address;
}contact_t;typedef struct
{string name;int age;
}parents_t;typedef struct
{string name;int age;int id;contact_t contact_ways;parents_t parents[2];
}student_t;student_t st[3];//打印出学生资料,来验证读取文件信息是否成功
void stu_info_dump()
{for (int i = 0; i < 3; i++){printf("第%d个学生\n",i+1);cout << "name:" << st[i].name << endl;cout << "id:" << st[i].id << endl;cout << "age:" << st[i].age << endl;cout << "contact address:" << st[i].contact_ways.address << endl;cout << "contact number:" << st[i].contact_ways.phone_num << endl;cout << "father name:" << st[i].parents[0].name << endl;cout << "father age:" << st[i].parents[0].age << endl;cout << "mother name:" << st[i].parents[1].name << endl;cout << "mother age:" << st[i].parents[1].age << endl;printf("\n\n");}
}int main(int argc, char** argv)
{FileStorage fs("student.xml", FileStorage::READ); //填入读操作memset(st, 0, sizeof(st));FileNode student_node = fs["student"];//读取根节点FileNodeIterator fni = student_node.begin(); //获取结构体数组迭代器FileNodeIterator fniEnd = student_node.end();int count = 0;for (; fni != fniEnd; fni++)//遍历  {st[count].name = (string)(*fni)["name"];st[count].id = (int)(*fni)["id"];st[count].age = (int)(*fni)["age"];//contact结构体内容FileNode contact = (*fni)["contact_ways"];st[count].contact_ways.address = (string)contact["address"];st[count].contact_ways.phone_num = (string)contact["phone_number"];//parents结构体数组内容FileNode parents = (*fni)["parents"];FileNodeIterator fni2 = parents.begin(); //获取结构体数组迭代器FileNodeIterator fniEnd2 = parents.end();int count2 = 0;for (; fni2 != fniEnd2; fni2++)//遍历  {st[count].parents[count2].name = (string)(*fni2)["name"];st[count].parents[count2].age = (int)(*fni2)["age"];count2++;}count++;}stu_info_dump();return 0;
}

打印如下,这表明xml的数据已经成功读入内存了。

OpenCV精进之路(零):HighGUI——读写XML和YML文件相关推荐

  1. OpenCV读写xml和yml文件

    有时候我们处理完图像后需要保存一下数据到文件上,以供下一步的处理.一个比较广泛的需求场景就是:我们对一幅图像进行特征提取之后,需要把特征点信息保存到文件上,以供后面的机器学习分类操作.那么如果遇到这样 ...

  2. .hpp文件_16、OpenCV读写XML和YML文件

    除了标准视频压缩之外,OpenCV还提供了一种机制,用于以YAML或XML格式将其各种数据类型序列化和反序列化到磁盘和从磁盘进行反序列化.这些方法可用于在单个文件中加载或存储任意数量的OpenCV数据 ...

  3. OpenCV精进之路(十六):图像分解和融合技术——图像拼接和图像融合技术

    图像拼接在实际的应用场景很广,比如无人机航拍,遥感图像等等,图像拼接是进一步做图像理解基础步骤,拼接效果的好坏直接影响接下来的工作,所以一个好的图像拼接算法非常重要. 再举一个身边的例子吧,你用你的手 ...

  4. 【OpenCV】OpenCV实战从入门到精通之 -- 输入输出XML和YAML文件详解

    1.XML和YAML文件简介 XML文件是一种元标记语言,即开发者可以根据自身需要定义自己的标记.它是一种语义和结构语言,描述了文档的语义和结构. YAML以数据为中心,是一个可读性高,用来表达资料序 ...

  5. OpenCV精进之路(零):core组件——Mat和IplImage访问像素的方法总结

    在opencv的编程中,遍历访问图像元素是经常遇到的操作,掌握其方法非常重要,无论是Mat类的像素访问,还是IplImage结构体的访问的方法,都必须扎实掌握,毕竟,图像处理本质上就是对像素的各种操作 ...

  6. OpenCV精进之路(零):core组件——绘制点、直线、几何图形

    绘制点和圆 void cvCircle( CvArr* img, CvPoint center, int radius, CvScalar color,int thickness=1, int lin ...

  7. OpenCV精进之路(零):访问图像中像素的三种方法

    访问像素的三种方法 指针访问:最快 迭代器iterator:较慢,非常安全,指针访问可能出现越界问题 动态地址计算:更慢,通过at()实现.适用于访问具体某个第i行,j列的像素,而不适用遍历像素 这里 ...

  8. OpenCV精进之路(十三):角点检测

    角点检测是计算机视觉系统中用来获取图像特征的一种方法.我们都常说,这幅图像很有特点,但是一问他到底有哪些特点,或者这幅图有哪些特征可以让你一下子就识别出该物体,你可能就说不出来了.其实说图像的特征,你 ...

  9. OpenCV精进之路(二十三):实例——Bag of Features(BoF)图像分类实践

    在深度学习在图像识别任务上大放异彩之前,词袋模型Bag of Features一直是各类比赛的首选方法.首先我们先来回顾一下PASCAL VOC竞赛历年来的最好成绩来介绍物体分类算法的发展. 从上表我 ...

最新文章

  1. kafka 异步发送阻塞_Kafka学习一
  2. AngularJS 国际化——Angular-translate
  3. mysql 打开文件数_MySQL打开的文件描述符限制
  4. 常考数据结构与算法:设计getMin功能的栈
  5. 3.2.1 造成误差的原因分析
  6. Hadoop中Context类的作用
  7. java类加载器 架构 设计_类加载器(DexClassLoader)与插件化(动态加载)
  8. Android 控件之RatingBar评分条(五星)自定义样式
  9. 重构老系统遗留代码的一些方法学习笔记
  10. python和sqlserver应用_Windows和Linux下使用Python访问SqlServer的方法介绍
  11. XAML实例教程系列 - 资源(Resources)
  12. python excel 单元格格式_python设置单元格数值格式
  13. nodejs 中es5 模块的几种写法
  14. 算法面试:精选微软经典的算法面试100题(第21-25题)
  15. 打印机服务器不支持1020,Win7系统安装hp1020打印机后无法使用如何解决
  16. 吊打面试官了解一下?2021年字节跳动春招面试题详解(附详细答案)
  17. matlab中log和复数表示,matlab复数表示
  18. 听说crmeb多商户增加了种草功能?
  19. 快速批量生成双排标签序列号
  20. 英语月份、星期、日期的缩写

热门文章

  1. 【李宏毅2020 ML/DL】P76 Generative Adversarial Network | Unsupervised Conditional Generation
  2. 效果良好!构造一个输入速度的神经网络,以DQN方式实现小游戏的自动控制
  3. Android开发实践:Java层与Jni层的数组传递
  4. Windows IO 性能简单测试
  5. Velocity - 单例还是非单例
  6. linux学习笔记(三):文件系统结构
  7. python坐标系 向量分量_关于Python中的向量相加和numpy中的向量相加效率对比
  8. 系统学习 TypeScript(三)——基础类型
  9. 你知道怎么离线安装全局 node 模块吗?
  10. BlackBerry 应用程序开发者指南 第二卷:高级--第13章 应用程序间共享运行时对象...