Opencv探索之路(十九):读写xml和yml文件
2017-07-15 12:27
411 查看
有时候我们处理完图像后需要保存一下数据到文件上,以供下一步的处理。一个比较广泛的需求场景就是:我们对一幅图像进行特征提取之后,需要把特征点信息保存到文件上,以供后面的机器学习分类操作。那么如果遇到这样的场景,我们有什么好方法,搭建这类的小型数据库文件?我第一时间想到的是把这些数据全写到文件上,下次我们需要这些数据就把他们从文件里读出来就好了。
其实更好的办法是使用xml和yml,因为他们更具有可读性,简直就是为保存数据结构而生的好方法!OpenCV提供了很好用的读写xml/yml的类,我们只要掌握其读写要领,很容易就可以实现这个小型数据库。
打开test.xml文件,我们看到我们的数据保存是这样子的:
如果我们将文件存为test.yml,即
那么我们最终的得到的test.yml是这样子的:
我们还可以保存为txt格式
打开看是这样的:
我们还还可以保存为doc文件!
打开看是这样子的:
我们可以看出,显然yml文件的排版更加简洁明了,xml文件却显得有点冗余和杂乱了。
打开student.xml文件,如下
若存储的是yml文件,打开如下:
打印如下:
打印如下,这表明xml的数据已经成功读入内存了。
其实更好的办法是使用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 FileStorage类读写XML/YML文件
- OpenCV FileStorage类读写XML/YML文件
- OpenCV FileStorage类读写XML/YML文件
- opencv读写xml 、yml文件
- OpenCV FileStorage类读写XML/YML文件
- OPenCv采用FileStorage类读写xml或者yml文件----程序
- OpenCV读写xml和yml文件
- OpenCV FileStorage类读写XML/YML文件
- java读写xml文件
- xml文件内容的读写
- 九、python读写xml文件
- WPF读写config配置文件及XML数据的学习
- opencv下XML 文件的读写 很全滴
- java读写xml和properties配置文件and Properties支持中文(转)
- 使用dom4j 读写xml文件
- c#读写xml文件
- android 学习笔记2-logcat 内外部文件的存储 文件权限 xml读写
- C#读写XML文件
- [转]Matlab 7.0 中XML文件读写测试
- c#读写xml文件