本文作者:小嗷
微信公众号:aoxiaoji
吹比QQ群:736854977
Google、百度、face++、凡是涉及有关物体识别公司,他们最值钱不是算法什么,而是那份保存成千上万样本文件。当然,文件格式也是千奇百怪。今天就说说最经常用到文件格式XML。
如果大家有做过人脸识别就可以体会到,用主分量分析法得到的特征脸、平均脸等等数据都会被保存成为XML格式
本文你会找到以下问题的答案:
如何使用YAML或XML文件打印和读取文本条目到文件和OpenCV中?
如何对OpenCV数据结构进行同样的操作?
如何为您的数据结构做这些?
使用OpenCV数据结构,如cv::FileStorage, cv::FileNode或cv::FileNodeIterator。
用途:生成数据文件(如下官方自带生成的识别文件)
haarcascadeeye和haarcascadesmile分别代表是眼睛识别和微笑识别的数据文件
YAML:http://www.yaml.org
3.1 FileStorage
XML/YAML/JSON文件存储类,它封装了从文件中写入或读取数据所需的所有信息。
API函数网址:
https://docs.opencv.org/master/da/d56/classcv11FileStorage.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++代码如下:
1// ConsoleApplication3.cpp : 定义控制台应用程序的入口点。 2// 3#include "stdafx.h" 4#include <iostream> 5#include <fstream> 6using namespace std; 7int main() 8{ 9 char *path;10 string ns = "C://1.txt";11 path = (char*)ns.c_str();12 ofstream fout;13 fout.open(path);14 if (fout) { // 如果创建成功15 fout << 123 << endl; // 使用与cout同样的方式进行写入16 fout.close(); // 执行完操作后关闭文件句柄17 }18 else19 {20 getchar();21 }22 return 0;23}
结果如下
任务一:XML与YAML的文件写入
任务二:XML与YAML的文件写入
步骤:
第一步:XML、YAML文件的打开
在Opencv中,使用FileStorage进行文件读写。XML文件操作与YAML一样,不过存在一些细小差别。
1string fileName = "abc.xml" 2// write file3FileStorage fs(fileName , FileStorage::WRITE);4// read file5FileStorage fs2(fileName, FileStorage::READ);6// or use: cv::FileStorage::open7fs2.open(fileName , FileStorage::READ);
文档打开后很关心的一件事就是,进行确认是否成功。FileStorage有自己的成员函数返回文件打开状态:
1// bool FileStorage::isOpened() const; 2if ( !fs.isOpened() ) // failed 3{ 4 cout<<"Save File Failed!"<<endl; 5 return ; 6} 7else // succeed 8{ 9 ...10}
第二步:进行文件读写操作
FileStorage文件读与写的方法与C++语言中的文件流对象的使用很像,对>>和<<进行了重载,分别用于文件读取和写入。很棒的是,FileStorage支持一些常用格式的直接读写,例如字符、字符串、数字、cv::Mat等。对于不支持的数据结构,只能按照规则自己去写啦~
1fs << "frameCount" << 5; // 字符和数字2Mat_<double> cameraMat = Mat_<double>::zeros(3, 3); 3fs << "Camera Intrinsic Matrix" << cameraMat;
注意:
- fs << "frameCount" <<5中""内输出的字符串是有限制的,对于YAML有效范围是:[a-z],[A-Z],[0-9],”-“,”_”和空格。XML与YAML基本一致,但是YAML字符之间加空格是允许的,XML不允许。如果出现以下BUG,请不要慌张,检查一下输入的字符是否有效就OK~
读取
文件读取的方法有两种:
1// first method: use (type) operator on FileNode.2int frameCount = (int)fs2["frameCount"];3// second second method: use cv::FileNode::operator >>4int frameCount;5fs2["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/tutorialfileinputyml.htmlwithxmlyml.html
第三步:文件关闭
fs.release();
写入XML或YAML文件
代码如下
1//---------------------------------【头文件、命名空间包含部分】------------------------------- 2// 描述:包含程序所使用的头文件和命名空间 3//------------------------------------------------------------------------------------------------ 4#include "opencv2/opencv.hpp" 5#include <time.h> 6using namespace cv; 7//-----------------------------------【main( )函数】-------------------------------------------- 8// 描述:控制台应用程序的入口函数,我们的程序从这里开始 9//-----------------------------------------------------------------------------------------------10int main( ) 11{ 12 //改变console字体颜色13 system("color 5F"); 14 //初始化15 FileStorage fs("test.yaml", FileStorage::WRITE); 16 //开始文件写入17 fs << "frameCount" << 5; 18 time_t rawtime; time(&rawtime); 19 fs << "calibrationDate" << asctime(localtime(&rawtime)); 20 Mat cameraMatrix = (Mat_<double>(3,3) << 1000, 0, 320, 0, 1000, 240, 0, 0, 1); 21 Mat distCoeffs = (Mat_<double>(5,1) << 0.1, 0.01, -0.001, 0, 0); 22 fs << "cameraMatrix" << cameraMatrix << "distCoeffs" << distCoeffs; 23 fs << "features" << "["; 24 for( int i = 0; i < 3; i++ ) 25 { 26 int x = rand() % 640; 27 int y = rand() % 480; 28 uchar lbp = rand() % 256; 29 fs << "{:" << "x" << x << "y" << y << "lbp" << "[:"; 30 for( int j = 0; j < 8; j++ ) 31 fs << ((lbp >> j) & 1); 32 fs << "]" << "}"; 33 } 34 fs << "]"; 35 fs.release(); 36 printf("\n文件读写完毕,请在工程目录下查看生成的文件~");37 getchar();38 return 0; 39}
读XML或YAML文件
代码如下:
1//---------------------------------【头文件、命名空间包含部分】------------------------------- 2// 描述:包含程序所使用的头文件和命名空间 3//------------------------------------------------------------------------------------------------ 4#include "opencv2/opencv.hpp" 5#include <time.h> 6using namespace cv; 7using namespace std; 8int main() 9{10 //改变console字体颜色11 system("color 6F");12 //初始化13 FileStorage fs2("test.yaml", FileStorage::READ);14 // 第一种方法,对FileNode操作15 int frameCount = (int)fs2["frameCount"];16 std::string date;17 // 第二种方法,使用FileNode运算符> > 18 fs2["calibrationDate"] >> date;19 Mat cameraMatrix2, distCoeffs2;20 fs2["cameraMatrix"] >> cameraMatrix2;21 fs2["distCoeffs"] >> distCoeffs2;22 cout << "frameCount: " << frameCount << endl23 << "calibration date: " << date << endl24 << "camera matrix: " << cameraMatrix2 << endl25 << "distortion coeffs: " << distCoeffs2 << endl;26 FileNode features = fs2["features"];27 FileNodeIterator it = features.begin(), it_end = features.end();28 int idx = 0;29 std::vector<uchar> lbpval;30 //使用FileNodeIterator遍历序列31 for (; it != it_end; ++it, idx++)32 {33 cout << "feature #" << idx << ": ";34 cout << "x=" << (int)(*it)["x"] << ", y=" << (int)(*it)["y"] << ", lbp: (";35 // 我们也可以使用使用filenode > > std::vector操作符很容易的读数值阵列36 (*it)["lbp"] >> lbpval;37 for (int i = 0; i < (int)lbpval.size(); i++)38 cout << " " << (int)lbpval[i];39 cout << ")" << endl;40 }41 fs2.release();42 //程序结束,输出一些帮助文字43 printf("\n文件读取完毕,请输入任意键结束程序~");44 getchar();45 return 0;46}
FileNode类的API网址:
https://docs.opencv.org/master/de/dd9/classcv11FileNode.html
如果不懂的话,QQ或者微信公众号通知一声。
1.写操作效果图
2.读操作效果图
本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)
大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年
写文章主要是为了后人少走点弯路,多交点朋友,一起学习
如果有好的图像识别群拉我进去QQ:631821577
就我一个白板,最后还是成的,你们别怕,慢慢来把
分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。
QQ群:736854977
有什么疑问公众号提问,下班或者周六日回答,ths
API文档:opencv2refman.pdf(Ctrl + F查找相关bitwise_and(),就会有它的定义和各个参数意思)
密码:ev4g
推荐文章: