16.物体识别的重要数据文件(XML和YAML文件) — OpenCV从零开始到图像(人脸 + 物体)识别系列
本文作者:小嗷
微信公众号:aoxiaoji
吹比QQ群:736854977
简书链接:https://www.jianshu.com/u/45da1fbce7d0
本文你会找到以下问题的答案:
- 如何使用YAML或XML文件打印和读取文本条目到文件和OpenCV中?
- 如何对OpenCV数据结构进行同样的操作?
- 如何为您的数据结构做这些?
- 使用OpenCV数据结构,如cv::FileStorage, cv::FileNode或cv::FileNodeIterator。
用途:生成数据文件(如下官方自带生成的识别文件)
haarcascade_eye和haarcascade_smile分别代表是眼睛识别和微笑识别的数据文件
YAML:http://www.yaml.org XML :http://www.w3c.org/XML
3.1 FileStorage
XML/YAML/JSON文件存储类,它封装了从文件中写入或读取数据所需的所有信息。
API函数网址:
https://docs.opencv.org/master/da/d56/classcv_1_1FileStorage.html#details
(1)实例化一个FileStorage类的对象,用默认带参数构造,完成初始化,或者用FileStorage::open()成员函数辅助初始化。当然,FileStorage构造函数一共有三个具体情况,视情况而定。
如上图FileStorage构造函数第二个:
参数
filename:要打开的文件的名称或文本字符串来读取数据。
flags:选择操作模式。
encoding:文件的编码。
注意,目前不支持UTF-16 XML编码,您应该使用8位编码而不是它。
flags:操作模式有如下
读写添加,还有保存在内存缓冲区里,什么格式等等。
(2)使用流操作符<<进行文件写入操作,或者>>进行文件读取操作,类似C++中的文件输入输出流。
(3)使用FileStorage::release()函数析构掉FileStorage类对象,同时关闭文件
也就是我们只需要完成FileStorage三部曲,就学习这种OpenCV基础及重要的XML,JSON,YXML读取写入操作。
当然,各位可能说如何创建一个新的XML文件?
默认打开的时候,如果没有该文件就自动创建文件,打开成功fout返回true,利用true来判断是否创建成功。VC++代码如下:
// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char *path;
string ns = "C://1.txt";
path = (char*)ns.c_str();
ofstream fout;
fout.open(path);
if (fout) { // 如果创建成功
fout << 123 << endl; // 使用与cout同样的方式进行写入
fout.close(); // 执行完操作后关闭文件句柄
}
else
{
getchar();
}
return 0;
}
结果如下
任务一:XML与YAML的文件写入
任务二:XML与YAML的文件写入
步骤:
第一步:XML、YAML文件的打开
在Opencv中,使用FileStorage进行文件读写。XML文件操作与YAML一样,不过存在一些细小差别。
string fileName = "abc.xml"
// write file
FileStorage fs(fileName , FileStorage::WRITE);
// read file
FileStorage fs2(fileName, FileStorage::READ);
// or use: cv::FileStorage::open
fs2.open(fileName , FileStorage::READ);
文档打开后很关心的一件事就是,进行确认是否成功。FileStorage有自己的成员函数返回文件打开状态:
// bool FileStorage::isOpened() const;
if ( !fs.isOpened() ) // failed
{
cout<<"Save File Failed!"<<endl;
return ;
}
else // succeed
{
...
}
第二步:进行文件读写操作
FileStorage文件读与写的方法与C++语言中的文件流对象的使用很像,对>>和<<进行了重载,分别用于文件读取和写入。很棒的是,FileStorage支持一些常用格式的直接读写,例如字符、字符串、数字、cv::Mat等。对于不支持的数据结构,只能按照规则自己去写啦~
fs << "frameCount" << 5; // 字符和数字
Mat_<double> cameraMat = Mat_<double>::zeros(3, 3);
fs << "Camera Intrinsic Matrix" << cameraMat;
注意:
- fs << “frameCount” <<5中”“内输出的字符串是有限制的,对于YAML有效范围是:[a-z],[A-Z],[0-9],”-“,”_”和空格。XML与YAML基本一致,但是YAML字符之间加空格是允许的,XML不允许。如果出现以下BUG,请不要慌张,检查一下输入的字符是否有效就OK~
读取
文件读取的方法有两种:
// first method: use (type) operator on FileNode.
int frameCount = (int)fs2["frameCount"];
// second second method: use cv::FileNode::operator >>
int frameCount;
fs2["frameCount"] >> frameCount;
读写还有类型如下
- Input and Output of text and numbers.
- Input/Output of OpenCV Data structures. (opencv自带Mat)
- Input/Output of vectors (arrays) and associative maps.(数组和maps)
- Read and write your own data structures.(你自己的数据类型)
具体查考:
https://docs.opencv.org/master/dd/d74/tutorial_file_input_output_with_xml_yml.html
第三步:文件关闭
fs.release();
写XML或YAML代码如下
//---------------------------------【头文件、命名空间包含部分】-------------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include "opencv2/opencv.hpp"
#include <time.h>
using namespace cv;
//-----------------------------------【main( )函数】--------------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始
//-----------------------------------------------------------------------------------------------
int main( )
{
//改变console字体颜色
system("color 5F");
//初始化
FileStorage fs("test.yaml", 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();
printf("\n文件读写完毕,请在工程目录下查看生成的文件~");
getchar();
return 0;
}
读代码如下:
//---------------------------------【头文件、命名空间包含部分】-------------------------------
// 描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------------------------------------
#include "opencv2/opencv.hpp"
#include <time.h>
using namespace cv;
using namespace std;
int main()
{
//改变console字体颜色
system("color 6F");
//初始化
FileStorage fs2("test.yaml", FileStorage::READ);
// 第一种方法,对FileNode操作
int frameCount = (int)fs2["frameCount"];
std::string date;
// 第二种方法,使用FileNode运算符> >
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;
//使用FileNodeIterator遍历序列
for (; it != it_end; ++it, idx++)
{
cout << "feature #" << idx << ": ";
cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";
// 我们也可以使用使用filenode > > std::vector操作符很容易的读数值阵列
(*it)["lbp"] >> lbpval;
for (int i = 0; i < (int)lbpval.size(); i++)
cout << " " << (int)lbpval[i];
cout << ")" << endl;
}
fs2.release();
//程序结束,输出一些帮助文字
printf("\n文件读取完毕,请输入任意键结束程序~");
getchar();
return 0;
}
FileNode类的API网址:
https://docs.opencv.org/master/de/dd9/classcv_1_1FileNode.html
如果不懂的话,QQ或者微信通知一声。
1.写操作效果图
2.读操作效果图
- 本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)
- 大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年
- 写文章主要是为了后人少走点弯路,多交点朋友,一起学习
- 如果有好的图像识别群拉我进去QQ:631821577
- 就我一个白板,最后还是成的,你们别怕,慢慢来把
分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。
- 邮箱:631821577@qq.com
- QQ群:736854977
- 有什么疑问公众号提问,下班或者周六日回答,ths
- API文档:opencv2refman.pdf(Ctrl + F查找相关bitwise_and(),就会有它的定义和各个参数意思)
- 百度链接:https://pan.baidu.com/s/1xn6cTTZAGSxdAAtrIenhPw
- 密码:ev4g
推荐文章: