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

其实更好的办法是使用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: Kobe
age: 21
id: 1
contact_ways:
phone_number: "123"
address: "1st building"
parents:
-
name: dad
age: 40
-
name: mum
age: 39
-
name: James
age: 20
id: 2
contact_ways:
phone_number: "12223"
address: "2st building"
parents:
-
name: daddy
age: 44
-
name: mumy
age: 38
-
name: ""
age: 0
id: 0
contact_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);
} //读入map
FileNode 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探索之路(十九):读写xml和yml文件的更多相关文章

  1. OpenCV探索之路(九):模板匹配

    模板匹配的作用在图像识别领域作用可大了.那什么是模板匹配? 模板匹配,就是在一幅图像中寻找另一幅模板图像最匹配(也就是最相似)的部分的技术. 说的有点抽象,下面给个例子说明就很明白了. 在上面这幅全明 ...

  2. OpenCV FileStorage类读写XML/YML文件

    本文转自:http://www.cnblogs.com/summerRQ/articles/2524560.html 在OpenCV程序中,需要保存中间结果的时候常常会使用.xml / .yml文件, ...

  3. 【VS开发】【计算机视觉】OpenCV读写xml文件《C++版本》

    OpenCV FileStorage类读写XML/YML文件 在OpenCV程序中,需要保存中间结果的时候常常会使用.xml / .yml文件,opencv2.0之前都是使用C风格的代码,当时读写XM ...

  4. python第二十九课——文件读写(复制文件)

    自定义函数:实现文件复制操作有形参(2个) 没有返回值相似版(不用) def copyFile(src,dest): #1.打开两个文件:1个关联读操作,1个关联写操作 fr=open(src,'rb ...

  5. python第二十九课——文件读写(读取读取中文字符)

    演示:读取中文字符 结论: 1).如果不设置encoding,默认使用gbk进行编解码 2).如果编码和解码不一致,最终导致报错,但是一旦设置了errors='ingore',那么就不会报错,而采取乱 ...

  6. 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十九:SDRAM模块② — 多字读写

    实验十九:SDRAM模块② — 多字读写 表示19.1 Mode Register的内容. Mode Register A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A ...

  7. centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数据库读写分离 双主搭建 mysql.history 第二十九节课

    centos  MySQL主从配置 ntsysv   chkconfig  setup命令  配置MySQL 主从 子shell  MySQL备份  kill命令  pid文件  discuz!论坛数 ...

  8. OpenCV探索之路(二十四)图像拼接和图像融合技术

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

  9. KALI LINUX WEB 渗透测试视频教程—第十九课-METASPLOIT基础

    原文链接:Kali Linux Web渗透测试视频教程—第十九课-metasploit基础 文/玄魂 目录 Kali Linux Web 渗透测试视频教程—第十九课-metasploit基础..... ...

随机推荐

  1. 将 FFmpeg 移植到 Android平台 (完整版)

    首先需要去FFmpeg的官网http://www.ffmpeg.org/去下载FFmpeg的源码,目前的版本号为FFmpeg3.3(Hilbert). 下载的文件为压缩包,解压后得到ffmpeg-3. ...

  2. 使用 Hive装载数据的几种方式

    装载数据 1.以LOAD的方式装载数据 LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION( ...

  3. 一张图搞懂容器所有操作 - 每天5分钟玩转 Docker 容器技术(26)

    前面我们已经讨论了容器的各种操作,对容器的生命周期有了大致的理解,下面这张状态机很好地总结了容器各种状态之间是如何转换的. 如果掌握了前面的知识,要看懂这张图应该不难.不过有两点还是需要补充一下: 可 ...

  4. 利用document的readyState去实现页面加载中的效果

    打开新的网页时,为了增强友好性体验,告知用户网页正在加载数据需要呈现一个"页面加载中"之类的提示,只需要利用document就可以实现. 实现示例代码如下: <style&g ...

  5. robot framework环境搭建

    来源:http://www.cnblogs.com/puresoul/p/3854963.html[转] 一. robot framework环境搭建: 官网:http://robotframewor ...

  6. js判断是否是ie浏览器且给出ie版本

    之前懒得写判断ie版本js,因为网上关于这方面的代码太多了,所以从网上拷贝了一个,放到项目上才发现由于时效性的问题,代码不生效.就自己写一个吧. 怎么去看浏览器的内核等信息 ---- js的全局对象w ...

  7. 大数据平台搭建-zookeeper集群的搭建

    本系列文章主要阐述大数据计算平台相关框架的搭建,包括如下内容: 基础环境安装 zookeeper集群的搭建 kafka集群的搭建 hadoop/hbase集群的搭建 spark集群的搭建 flink集 ...

  8. flask 扩展之 -- flask-pagedown

    支持 Markdown 语法, 并添加 富文本文章的预览功能. 使用到的包列表: PageDown : 使用 JavaScript 实现的客户端 Markdown 到 HTML 的转换程序. Flas ...

  9. thinkphp中find()和select()的区别

    1.find()是查找符合条件的第一条数据,返回的是一个一维数组: select()是查找符合条件的所有的数据,返回的是一个二维数组: 2.以下案例 $tech=M('techlevel','HR_C ...

  10. Oracle数据库ora-01722 错误小记

    今天遇到个关联查询的错误,特搜索了下记录下来. 因为做视图查询的表是以前建立的,所以有个字段类型应该只实用于当时.看SQL: select x.参数1 , y.参数2 from t_fac_info ...