博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Opencv探索之路(十九):读写xml和yml文件
阅读量:4515 次
发布时间:2019-06-08

本文共 9266 字,大约阅读时间需要 30 分钟。

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

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

xml/yml的写操作

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

一个简单数据写入的例子

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

#include
#include
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
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
::iterator it = m.begin(); for (; it != m.end(); it++) { fs << it->first << it->second; } fs << "}"; //map写入结束 return 0;}

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

1093303-20170715122343040-609433767.png

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

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

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

1093303-20170715122400540-945015257.png

我们还可以保存为txt格式

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

打开看是这样的:

1093303-20170715122419306-364394913.png

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

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

打开看是这样子的:

1093303-20170715122435368-1048301719.png

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

一个复杂写入的例子

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

#include
#include
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文件,如下

<_>
Kobe
21
1
"123"
"1st building"
<_>
dad
40
<_>
mum
39
<_>
James
20
2
"12223"
"2st building"
<_>
daddy
44
<_>
mumy
38
<_>
""
0
0
""
""
<_>
""
0
<_>
""
0

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

%YAML:1.0student:   -      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
#include
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
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;}

打印如下:

1093303-20170715122654009-1178811809.png

一个复杂读入的例子

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

#include
#include
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的数据已经成功读入内存了。

1093303-20170715122709181-1888802364.png

转载于:https://www.cnblogs.com/skyfsm/p/7182313.html

你可能感兴趣的文章
单例静态继承
查看>>
Android开发:《Gradle Recipes for Android》阅读笔记(翻译)3.2——设置Flavors和Variants...
查看>>
Android零基础入门第36节:Android系统事件的响应
查看>>
POJ 2262 Goldbach's Conjecture
查看>>
自己手动写代码实现数据库连接池
查看>>
领域对象驱动开发:来吧,让我们从对象开始吧
查看>>
mysql分区分表讲解
查看>>
java编程思想读书笔记三(11-21)
查看>>
luogu P5302 [GXOI/GZOI2019]特技飞行
查看>>
EntityFramework 开始小试
查看>>
234 Palindrome Linked List
查看>>
Keil-MDK编译完成后代码大小
查看>>
ArcGIS JS 学习笔记4 实现地图联动
查看>>
ubuntu 12.04 lts安装golang并设置vim语法高亮
查看>>
编程题目:PAT 1004. 成绩排名 (20)
查看>>
使用分层实现业务处理
查看>>
Microsoft Windows平台的NoSQL数据存储引擎
查看>>
浅谈虚拟机
查看>>
Ubuntu系统Linux编译osg库
查看>>
error MSB8008: 指定的平台工具集(v120)未安装或无效 解决办法
查看>>