Opencv探索之路(十九):读写xml和yml文件
有时候我们处理完图像后需要保存一下数据到文件上,以供下一步的处理。一个比较广泛的需求场景就是:我们对一幅图像进行特征提取之后,需要把特征点信息保存到文件上,以供后面的机器学习分类操作。那么如果遇到这样的场景,我们有什么好方法,搭建这类的小型数据库文件?我第一时间想到的是把这些数据全写到文件上,下次我们需要这些数据就把他们从文件里读出来就好了。
其实更好的办法是使用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文件的更多相关文章
- OpenCV探索之路(九):模板匹配
模板匹配的作用在图像识别领域作用可大了.那什么是模板匹配? 模板匹配,就是在一幅图像中寻找另一幅模板图像最匹配(也就是最相似)的部分的技术. 说的有点抽象,下面给个例子说明就很明白了. 在上面这幅全明 ...
- OpenCV FileStorage类读写XML/YML文件
本文转自:http://www.cnblogs.com/summerRQ/articles/2524560.html 在OpenCV程序中,需要保存中间结果的时候常常会使用.xml / .yml文件, ...
- 【VS开发】【计算机视觉】OpenCV读写xml文件《C++版本》
OpenCV FileStorage类读写XML/YML文件 在OpenCV程序中,需要保存中间结果的时候常常会使用.xml / .yml文件,opencv2.0之前都是使用C风格的代码,当时读写XM ...
- python第二十九课——文件读写(复制文件)
自定义函数:实现文件复制操作有形参(2个) 没有返回值相似版(不用) def copyFile(src,dest): #1.打开两个文件:1个关联读操作,1个关联写操作 fr=open(src,'rb ...
- python第二十九课——文件读写(读取读取中文字符)
演示:读取中文字符 结论: 1).如果不设置encoding,默认使用gbk进行编解码 2).如果编码和解码不一致,最终导致报错,但是一旦设置了errors='ingore',那么就不会报错,而采取乱 ...
- 【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十九:SDRAM模块② — 多字读写
实验十九:SDRAM模块② — 多字读写 表示19.1 Mode Register的内容. Mode Register A12 A11 A10 A9 A8 A7 A6 A5 A4 A3 A2 A1 A ...
- centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数据库读写分离 双主搭建 mysql.history 第二十九节课
centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数 ...
- OpenCV探索之路(二十四)图像拼接和图像融合技术
图像拼接在实际的应用场景很广,比如无人机航拍,遥感图像等等,图像拼接是进一步做图像理解基础步骤,拼接效果的好坏直接影响接下来的工作,所以一个好的图像拼接算法非常重要. 再举一个身边的例子吧,你用你的手 ...
- KALI LINUX WEB 渗透测试视频教程—第十九课-METASPLOIT基础
原文链接:Kali Linux Web渗透测试视频教程—第十九课-metasploit基础 文/玄魂 目录 Kali Linux Web 渗透测试视频教程—第十九课-metasploit基础..... ...
随机推荐
- Java IO流之文件流
一.文件流分类 二.FileInputStream 三.FileOutputStream 四.FileReader 五.FileWriter 六.文件流应用 1,复制或剪切文件 2,读取文件信息 应用 ...
- Javascript检测值
检测原始值用typeof javascript有五种原始类型,分别为字符串.数字.布尔值.null和undefined 判断一个值是什么类型的字符串,可以通过typeof typeof variabl ...
- java音视频编解码问题:16/24/32位位音频byte[]转换为小端序short[],int[],以byte[]转short[]为例
前言:Java默认采用大端序存储方式,实际编码的音频数据是小端序,如果处理单8bit的音频当然不需要做转换,但是如果是16bit或者以上的就需要处理成小端序字节顺序. 注:大.小端序指的是字节的存储顺 ...
- DiscuzX3.1搬家全过程
最近做了一个安全交流小社区,由于太卡了,之后换了服务器,要给论坛搬家 所以在这里写一下记录. 首先,搬家前要做好以下准备: 1.在网站后台-站长-数据库-备份-网站-Discuz! 和 UCenter ...
- HTML/XML/XPATH基础
Html超文本标记语言 网页上单击右键→查看源文件/查看源代码 Html基本结构 <html> 为文档根元素,所有元素都在内部进行 <head> ...
- vue 高德地图之玩转周边
前言:在之前的博客中,有成功引入高德地图,这是以前的地址 vue 调用高德地图. 因为一些需求,需要使用到地图的周边功能. 完整的项目代码请查看 我的github 一 .先看要实现的结果,参考了链 ...
- 用php+mysql+ajax实现淘宝客服或阿里旺旺聊天功能 之 前台页面
首先来看一下我已经实现的效果图: 消费者页面:(本篇随笔) (1)会显示店主的头像 (2)当前用户发送信息显示在右侧,接受的信息,显示在左侧 店主或客服页面:(下一篇随笔) (1)在左侧有一个列表 , ...
- ssh无密码登录远程主机
方法:在客户端生成公/私钥对,将私钥文件保存在客户端,再将公钥文件上传到服务器端(远程主机) 1.在客户端生成公/私钥对 cb@cb251#ssh-keygen...cb@cb251#ls .ssh/ ...
- AngularJS <a> 超链接标签不起作用?
问题描述: Angular JS app中,使用超链接标签<a href='location'>click</a> 不起作用. 解决方法: 如果你不巧配置了$locationP ...
- w3c编程挑战-初级脚本算法
之前偶然看到了w3c上的编程挑战题,就像拿来试试手,先做的是初级脚本算法,总体不难,如果有更好的方法,希望能一起交流! 1.翻转字符串 先把字符串转化成数组,再借助数组的reverse方法翻转数组顺序 ...