本系列文章由 @YhL_Leo 出品,转载请注明出处。

文章链接: http://blog.csdn.net/yhl_leo/article/details/47660943


本文参考Opencv 2.4.11 documentation整理对YAMLXML文件实现I/O操作的方法。

官网:YAML:http://www.yaml.org XML :http://www.w3c.org/XML

1.YAML与XML文件的打开和关闭

YAML格式的文件拓展名包括:.yml.yaml,两个都表示YAML文件;

XML格式的文件拓展名为: .xml

1.1 文件打开

在Opencv中,使用FileStorage进行文件读写。XML文件操作与YAML一样,不过存在一些细小差别。

std::string fileName  = "E:\\test.yml"; // YAML
std::string fileName2 = "E:\\test.xml"; // XML
// write file
cv::FileStorage fs(fileName , cv::FileStorage::WRITE);
// read file
cv::FileStorage fs2(fileName , cv::FileStorage::READ);
// or use: cv::FileStorage::open
fs2.open(fileName , cv::FileStorage::READ);

FileStorage的文件操作模式一共分为四种:READWRITEAPPENDMEMORY

文档打开后很关心的一件事就是,进行确认是否成功。FileStorage有自己的成员函数返回文件打开状态:

// bool FileStorage::isOpened() const;
if ( !fs.isOpened() ) // failed
{
std::cout<<"Save File Failed!"<<std::endl;
return ;
}
else // succeed
{
...
}

1.2 文件关闭

FileStorage文件关闭比较简单:

fs.release();

2.文件读写

FileStorage文件读与写的方法与C++语言中的文件流对象的使用很像,对>><<进行了重载,分别用于文件读取和写入。很棒的是,FileStorage支持一些常用格式的直接读写,例如字符、字符串、数字、cv::Mat等。对于不支持的数据结构,只能按照规则自己去写啦~

2.1 写入

fs << "frameCount" << 5;  // 字符和数字
cv::Mat_<double> cameraMat = cv::Mat_<double>::zeros(3, 3);
fs << "Camera Intrinsic Matrix" << cameraMat; // cv::Mat

注意:

  • fs << "frameCount" <<5""内输出的字符串是有限制的,对于YAML有效范围是:[a-z],[A-Z],[0-9],”-“,”_”和空格。XML与YAML基本一致,但是YAML字符之间加空格是允许的,XML不允许。如果出现以下BUG,请不要慌张,检查一下输入的字符是否有效就OK~

2.2 读取

文件读取的方法有两种:

// first method: use (type) operator on FileNode.
int frameCount = (int)fs2["frameCount"];
// second second method: use cv::FileNode::operator >>
int frameCount;
fs2["frameCount"] >> frameCount;

2.3 Mat的操作

这一点真的很不错,而且与C++的输入输出方法很接近(链接:常用的三种Mat类型):

cv::Mat_<double> cameraMat = cv::Mat_<double>::zeros(3, 3);
cv::Mat_<double> distCoeffes = ( cv::Mat_<double>(5, 1)<< 0.1, 0.01, -0.001, 0.0, 0.0 );
// C++
std::cout<<"Camera Matrix"<<std::endl<<cv::Mat::Mat(cameraMat)<<std::endl;
std::cout<<"Distortion Coefficients"<<std::endl<<cv::Mat::Mat(distCoeffes)<<std::endl;
// cv::FileStorage
fs << "Camera Matrix" << cameraMat;
fs << "Distortion Coefficients"<<distCoeffes;

运行结果对比如下:

C++

YAML

XML

2.4 集合的操作

Opencv中将集合分为两类:映射和序列。

映射集合(Mappings, 又称named collections):每个元素有一个名字或者说关键字,并且可以通过名字访问其数据,类似于Key-Value结构。使用方法为:

// Mappings write
int x(1.0), y(0.0);
fs << "features" << "["; // also can be "[:"
fs <<"{:" << "x" << x << "y" << "}" << "]";
  • "{""{:"输出的结果是不一样的,YAML使用":"后,使输出的文本具有Python的风格,映射集合会按照一行排列,不适用时,按照每个元素与其值单独一行的方法排列。XML使用":"后输出结果会有不同,但基本可以视为把":"忽略。

YAML {

YAML {:

XML {

XML {:

// Mappings read
cv::FileNode features = fs2["features"];
// 遍历查看
cv::FileNodeIterator it = features.begin();
std::cout<<
"x="<<(int)(*it)["x"]<<
" y="<<(int)(*it)["y"]<<
" z="<<(int)(*it)["z"]<<std::endl;

输出结果:

  • 编程的时候,不在Mapping的"{ }"外加上"[ ]"输出的效果是不一样的,而且在数据读取的时候,加上"[

    ]"
    的Mapping结构会被认为是Mapping结构,否则会出错,以上述的Mappings write代码为例: 对于 fs <<

    "fearures" << "[" << "{" << ... << "}" << "]"
    结构,用上述方法可以读取成功; 对于 fs

    << "features" << "{" << ... << "}"
    结构,用上述方法时就会出错:

序列集合(Sequences,又称unnamed collections):数据没有名字名字或者关键字,一般通过序号(indices)访问数据,例如最常见的数组。

与映射类似,序列集合需要在输出开始前加"[",结束后使用"]",并且"[:""["在输出风格上与映射集合类似。

// Sequences write
int mySeq[5] = {0, 1, 2, 3, 4};
fs << "mySeq" << "[";
for ( int idx=0; idx<5; idx++ )
{
fs << mySeq[idx];
}
fs << "]";
// Sequences read
cv::FileNode mySeq2 = fs2["mySeq"];
std::vector<int> seq;
cv::FileNodeIterator it = mySeq2.begin(), it_end = mySeq2.end();
for ( ; it != it_end; it++ )
{
seq.push_back( (int)( *it ) );
// std::cout<<(int)(*it)<<" "<<std::endl;
}

3.Opencv documentation 源码示例

下面贴出Opencv documentation中的示例代码,可以作为参考:

// file write
#include "opencv2/opencv.hpp"
#include <time.h> using namespace cv;
using namespace std; int main(int, char** argv)
{
FileStorage fs("test.yml", FileStorage::WRITE); fs << "frameCount" << 5;
time_t rawtime; time(&rawtime);
fs << "calibrationDate" << asctime(localtime(&rawtime));
Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1);
Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0);
fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs;
fs << "features" << "[";
for( int i = 0; i < 3; i++ )
{
int x = rand() % 640;
int y = rand() % 480;
uchar lbp = rand() % 256; fs << "{:" << "x" << x << "y" << y << "lbp" << "[:";
for( int j = 0; j < 8; j++ )
fs << ((lbp >> j) & 1);
fs << "]" << "}";
}
fs << "]";
fs.release();
return 0;
}
// results
%YAML:1.0
frameCount: 5
calibrationDate: "Fri Jun 17 14:09:29 2011\n"
cameraMatrix: !!opencv-matrix
rows: 3
cols: 3
dt: d
data: [ 1000., 0., 320., 0., 1000., 240., 0., 0., 1. ]
distCoeffs: !!opencv-matrix
rows: 5
cols: 1
dt: d
data: [ 1.0000000000000001e-01, 1.0000000000000000e-02,
-1.0000000000000000e-03, 0., 0. ]
features:
- { x:167, y:49, lbp:[ 1, 0, 0, 1, 1, 0, 1, 1 ] }
- { x:298, y:130, lbp:[ 0, 0, 0, 1, 0, 0, 1, 1 ] }
- { x:344, y:158, lbp:[ 1, 1, 0, 0, 0, 0, 1, 0 ] }
// file read
FileStorage fs2("test.yml", FileStorage::READ); // first method: use (type) operator on FileNode.
int frameCount = (int)fs2["frameCount"]; std::string date;
// second method: use FileNode::operator >>
fs2["calibrationDate"] >> date; Mat cameraMatrix2, distCoeffs2;
fs2["cameraMatrix"] >> cameraMatrix2;
fs2["distCoeffs"] >> distCoeffs2; cout << "frameCount: " << frameCount << endl
<< "calibration date: " << date << endl
<< "camera matrix: " << cameraMatrix2 << endl
<< "distortion coeffs: " << distCoeffs2 << endl; FileNode features = fs2["features"];
FileNodeIterator it = features.begin(), it_end = features.end();
int idx = 0;
std::vector<uchar> lbpval; // iterate through a sequence using FileNodeIterator
for( ; it != it_end; ++it, idx++ )
{
cout << "feature #" << idx << ": ";
cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
// you can also easily read numerical arrays using FileNode >> std::vector operator.
(*it)["lbp"] >> lbpval;
for( int i = 0; i < (int)lbpval.size(); i++ )
cout << " " << (int)lbpval[i];
cout << ")" << endl;
}
fs.release();

Opencv YAML和XML格式文件操作详解的更多相关文章

  1. Android的file文件操作详解

    Android的file文件操作详解 android的文件操作要有权限: 判断SD卡是否插入 Environment.getExternalStorageState().equals( android ...

  2. C语言文件操作详解

    C语言中没有输入输出语句,所有的输入输出功能都用 ANSI C提供的一组标准库函数来实现.文件操作标准库函数有: 文件的打开操作 fopen 打开一个文件 文件的关闭操作 fclose 关闭一个文件 ...

  3. 【转】 C语言文件操作详解

    转自:http://www.cnblogs.com/likebeta/archive/2012/06/16/2551780.html C语言中没有输入输出语句,所有的输入输出功能都用 ANSI C提供 ...

  4. android中的文件操作详解以及内部存储和外部存储(转载)

    原文链接:http://m.blog.csdn.net/article/details?id=17725989 摘要 其实安卓文件的操作和java在pc环境下的操作并无二致,之所以需要单独讲解是因为安 ...

  5. Unix/Linux环境C编程入门教程(41) C语言库函数的文件操作详解

     上一篇博客我们讲解了如何使用Linux提供的文件操作函数,本文主要讲解使用C语言提供的文件操作的库函数. 1.函数介绍 fopen(打开文件) 相关函数 open,fclose 表头文件 #in ...

  6. Python——文件操作详解

    python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目 ...

  7. 【转】 android中的文件操作详解以及内部存储和外部存储

    摘要 其实安卓文件的操作和Java在pc环境下的操作并无二致,之所以需要单独讲解是因为安卓系统提供了不同于pc的访问文件系统根路径的api,同时对一个应用的私有文件做了统一的管理.根据我的经验,初学者 ...

  8. C++文件操作详解(ifstream、ofstream、fstream)

    C++ 通过以下几个类支持文件的输入输出: ofstream: 写操作(输出)的文件类 (由ostream引申而来) ifstream: 读操作(输入)的文件类(由istream引申而来) fstre ...

  9. c++ 文件操作详解

    C++ 通过以下几个类支持文件的输入输出: ofstream: 写操作(输出)的文件类 (由ostream引申而来) ifstream: 读操作(输入)的文件类(由istream引申而来) fstre ...

随机推荐

  1. hiho1509 异或排序

    题目链接 题目大意: 给定一个长度为 n 的非负整数序列 a[1..n] 你需要求有多少个非负整数 S 满足以下两个条件: (1).0 ≤ S < 260 (2).对于所有 1 ≤ i < ...

  2. 初识Git(三)

    这次要记录一下对branch,merge的学习. 与先前一样创建一个pro文件夹,initi该文件夹,在该文件夹中新建一个空的MainCode.txt,然后add文本文件并且commit. 接下来我们 ...

  3. ActiveMQ学习笔记(6)----ActiveMQ整合Spring开发

    1. 添加依赖 spring 提供了对JMS的支持,需要添加Spring支持jms的包和Spring的核心包,如下: <dependency> <groupId>org.apa ...

  4. Intellij IDEA 2018.3激活破解方法(解决key is invalid)

    1.程序安装包: https://download.jetbrains.8686c.com/idea/ideaIU-2018.3.exe 2.破解补丁:http://idea.lanyus.com/j ...

  5. 联想lenovo 家用电脑安装win7 无法引导问题(新电脑安装系统时提示File:\Boot\BCD错误解决方案)

    安装方式 : 1.进入 PE 2.用 EasyimageX 恢复 GHO镜像 3.重启后出现  原因: 主要 是安装win7 时,格式 化选择为GUID模式. 处理: win7 以后,格式华时选择MB ...

  6. tab栏切换

    最简单的tab栏切换 html部分 <ul class="tab"> <li class="item">待支付(1)</li> ...

  7. 带入gRPC:gRPC Deadlines

    带入gRPC:gRPC Deadlines 原文地址:带入gRPC:gRPC Deadlines项目地址:https://github.com/EDDYCJY/go... 前言 在前面的章节中,已经介 ...

  8. C语言中头文件尖括号和引号的区别

    用include 引用头文件时,双引号和尖括号的区别: 1.双引号:引用非标准库的头文件,编译器首先在程序源文件所在目录查找,如果未找到,则去系统默认目录查找,通常用于引用用户自定义的头文件. 2.尖 ...

  9. vjudge A - Beautiful numbers

    A - Beautiful numbers Volodya is an odd boy and his taste is strange as well. It seems to him that a ...

  10. 【转】Geometry cannot have Z values

    http://blog.csdn.net/tweeenty/article/details/44246407 在对矢量要素类添加要素,进行赋几何信息时(FeatureBuffer.Shape = IG ...