1.目的
(1)如何将文本写入XML或者YAML文件,及如何利用openCV读取XML和YAML文件
(2)如何利用YAML和XML文件存取openCV数据结构
(3)如何利用YAML或XML存取自定义数据结构
(4)openCV中数据结构的使用方法FileStorage,FileNode,FileNodeIterator
2.部分代码解释
(1)构造一个自己的数据结构(用类来定义),在MyData类中定义了类的数据成员的读写read&write
class MyData{
public:
int A;
double X;
string id;
public:
MyData():A(0),X(0),id(){}
//防止隐式转换
explicit MyData(int):A(97),X(CV_PI),id("mydata"){}
void write(FileStorage& fs){
fs << "A" << A << "X" << X << "id" << id;
}
void read(FileNode& node){
A = (int)node["A"];
X = (double)node["X"];
id = (string)node["id"];
}
};
(2)定义外部读写函数
//外部写函数调用内部函数实现对象的写操作
void write(FileStorage& fs, MyData& myData){
myData.write(fs);
}
//外部读函数调用内部函数实现对象的读操作
void read(FileNode& node, MyData& myData, MyData defaultValue = MyData()){
if(node.empty()){
myData = defaultValue;
}else{
myData.read(node);
}
}
(3)运算符重载
//cout << 重载
ostream& operator<<(ostream& out, MyData& myData){
out << "{id=" << myData.id << ",";
out << "X=" << myData.X << ",";
out << "A=" << myData.A << "}";
return(out);
}
//FileStorage << 重载
FileStorage& operator<<(FileStorage& fs, MyData& myData){
fs << "myData" << "{";
fs << "id" << myData.id;
fs << "X" << myData.X;
fs << "A" << myData.A;
fs << "}";
return(fs);
}
//FileNode >>重载
MyData& operator>>(FileNode& node, MyData& myData){
myData.read(node);
return(myData);
}
(4)文件写
//使用openCV中的FileStorage读写文件
//FileStorage::WRITE定义文件的操作方式
//文件的操作方式包括:WRITE,READ,APPEND
FileStorage fs(filename, FileStorage::WRITE);
(5)文件写操作
{//write
fs << "iterationNr" << 100;
//文本序列,只有全部读取才能获得相应元素
fs << "strings" << "[";
fs << "lena.jpg" << "awesomeness" << "baboon.jpg";
fs << "]";
//文本映射表,可以通过键值对的方式访问元素
fs << "mapping" << "{";
fs << "One" << 1;
fs << "Two" << 2;
fs << "}";
//矩阵
fs << "R" << R;
fs << "I" << I;
fs << myData;
//显式关闭文件
fs.release();
cout << "write done!!!" << endl;
}
(6)文件读操作
{//read
FileStorage fs(filename, FileStorage::READ);
int iterationNr;
fs["iterationNr"] >> iterationNr;
//获取映射表
FileNode node = fs["mapping"];
cout << iterationNr << endl;
cout << (int)node["One"] << " " << (int)node["Two"] << endl;
//获取数据流序列
node = fs["strings"];
//数据流需要通过迭代器来访问元素
FileNodeIterator begin = node.begin();
FileNodeIterator end = node.end();
for(;begin!=end; ++begin){
cout << (string)*begin << endl;
}
//读取矩阵
Mat R_, I_;
MyData m;
fs["R"] >> R_;
fs["I"] >> I_;
cout << endl << R_ << endl;
cout << I_ << endl;
//读取MyData数据格式
node = fs["myData"];
//调用上述重载的运算符
node >> m;
//调用上述重载的运算符
cout << endl << m << endl;
cout << "read done!!!" << endl;
}
3.完整代码
(1)CommonInclude.h
#ifndef COMMON_INCLUDE
#define COMMON_INCLUDE
#include
#include
#include
#include
using namespace std;
using namespace cv;
#endif
(2)FileRW.cpp
#include "CommonInclude.h"
#include
class MyData{
public:
int A;
double X;
string id;
public:
MyData():A(0),X(0),id(){}
//防止隐式转换
explicit MyData(int):A(97),X(CV_PI),id("mydata"){}
void write(FileStorage& fs){
fs << "A" << A << "X" << X << "id" << id;
}
void read(FileNode& node){
A = (int)node["A"];
X = (double)node["X"];
id = (string)node["id"];
}
};
void write(FileStorage& fs, MyData& myData){
myData.write(fs);
}
void read(FileNode& node, MyData& myData, MyData defaultValue = MyData()){
if(node.empty()){
myData = defaultValue;
}else{
myData.read(node);
}
}
//操作符号重载
ostream& operator<<(ostream& out, MyData& myData){
out << "{id=" << myData.id << ",";
out << "X=" << myData.X << ",";
out << "A=" << myData.A << "}";
return(out);
}
//<<重定义
FileStorage& operator<<(FileStorage& fs, MyData& myData){
fs << "myData" << "{";
fs << "id" << myData.id;
fs << "X" << myData.X;
fs << "A" << myData.A;
fs << "}";
return(fs);
}
//>>重定义
MyData& operator>>(FileNode& node, MyData& myData){
myData.read(node);
return(myData);
}
int main(int argc, char** argv){
if(argc < 2){
cout << "more parameters are required!!!" << endl;
return(-1);
}
char* filename = argv[1];
Mat R = Mat_::zeros(3,3);
Mat I = Mat_<double>::eye(3,3);
FileStorage fs(filename, FileStorage::WRITE);
MyData myData = MyData(1);
{//write
fs << "iterationNr" << 100;
//文本序列,只有全部读取才能获得相应元素
fs << "strings" << "[";
fs << "lena.jpg" << "awesomeness" << "baboon.jpg";
fs << "]";
//文本映射表
fs << "mapping" << "{";
fs << "One" << 1;
fs << "Two" << 2;
fs << "}";
fs << "R" << R;
fs << "I" << I;
fs << myData;
//显式关闭文件
fs.release();
cout << "write done!!!" << endl;
//cout << myData;
//write(fs, myData);
}
{//read
FileStorage fs(filename, FileStorage::READ);
int iterationNr;
fs["iterationNr"] >> iterationNr;
//获取映射表
FileNode node = fs["mapping"];
cout << iterationNr << endl;
cout << (int)node["One"] << " " << (int)node["Two"] << endl;
//获取数据流序列
node = fs["strings"];
FileNodeIterator begin = node.begin();
FileNodeIterator end = node.end();
for(;begin!=end; ++begin){
cout << (string)*begin << endl;
}
//读取矩阵
Mat R_, I_;
MyData m;
fs["R"] >> R_;
fs["I"] >> I_;
cout << endl << R_ << endl;
cout << I_ << endl;
//读取MyData数据格式
node = fs["myData"];
node >> m;
cout << endl << m << endl;
//cout << endl << (double)node["X"] << endl;
cout << "read done!!!" << endl;
}
return(0);
}
PS:为了让读者一目了然,我将类的定义和函数实现都写在一个cpp中,实际大工程中不建议着吗做!!!
参考文献
1.http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/core/file_input_output_with_xml_yml/file_input_output_with_xml_yml.html#fileinputoutputxmlyaml