本文作者:小嗷
微信公眾號(hào):aoxiaoji
吹比QQ群:736854977
Google亩码、百度藏古、face++城榛、凡是涉及有關(guān)物體識(shí)別公司,他們最值錢不是算法什么翔试,而是那份保存成千上萬樣本文件。當(dāng)然,文件格式也是千奇百怪。今天就說說最經(jīng)常用到文件格式XML扇救。
如果大家有做過人臉識(shí)別就可以體會(huì)到刑枝,用主分量分析法得到的特征臉、平均臉等等數(shù)據(jù)都會(huì)被保存成為XML格式
本文你會(huì)找到以下問題的答案:
如何使用YAML或XML文件打印和讀取文本條目到文件和OpenCV中?
如何對OpenCV數(shù)據(jù)結(jié)構(gòu)進(jìn)行同樣的操作?
如何為您的數(shù)據(jù)結(jié)構(gòu)做這些?
使用OpenCV數(shù)據(jù)結(jié)構(gòu)迅腔,如cv::FileStorage, cv::FileNode或cv::FileNodeIterator装畅。
用途:生成數(shù)據(jù)文件(如下官方自帶生成的識(shí)別文件)
haarcascadeeye和haarcascadesmile分別代表是眼睛識(shí)別和微笑識(shí)別的數(shù)據(jù)文件
YAML:http://www.yaml.org
3.1 FileStorage
XML/YAML/JSON文件存儲(chǔ)類,它封裝了從文件中寫入或讀取數(shù)據(jù)所需的所有信息钾挟。
API函數(shù)網(wǎng)址:
https://docs.opencv.org/master/da/d56/classcv11FileStorage.html#details
(1)實(shí)例化一個(gè)FileStorage類的對象洁灵,用默認(rèn)帶參數(shù)構(gòu)造,完成初始化掺出,或者用FileStorage::open()成員函數(shù)輔助初始化徽千。當(dāng)然,F(xiàn)ileStorage構(gòu)造函數(shù)一共有三個(gè)具體情況汤锨,視情況而定双抽。
如上圖FileStorage構(gòu)造函數(shù)第二個(gè):
參數(shù)
filename:要打開的文件的名稱或文本字符串來讀取數(shù)據(jù)。
flags:選擇操作模式闲礼。
encoding:文件的編碼牍汹。
注意,目前不支持UTF-16 XML編碼柬泽,您應(yīng)該使用8位編碼而不是它慎菲。
flags:操作模式有如下
讀寫添加,還有保存在內(nèi)存緩沖區(qū)里锨并,什么格式等等露该。
(2)使用流操作符<<進(jìn)行文件寫入操作,或者>>進(jìn)行文件讀取操作第煮,類似C++中的文件輸入輸出流解幼。
(3)使用FileStorage::release()函數(shù)析構(gòu)掉FileStorage類對象,同時(shí)關(guān)閉文件
也就是我們只需要完成FileStorage三部曲包警,就學(xué)習(xí)這種OpenCV基礎(chǔ)及重要的XML撵摆,JSON,YXML讀取寫入操作害晦。
當(dāng)然特铝,各位可能說如何創(chuàng)建一個(gè)新的XML文件?
默認(rèn)打開的時(shí)候篱瞎,如果沒有該文件就自動(dòng)創(chuàng)建文件苟呐,打開成功fout返回true,利用true來判斷是否創(chuàng)建成功俐筋。VC++代碼如下:
1// ConsoleApplication3.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)牵素。 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) { // 如果創(chuàng)建成功15 fout << 123 << endl; // 使用與cout同樣的方式進(jìn)行寫入16 fout.close(); // 執(zhí)行完操作后關(guān)閉文件句柄17 }18 else19 {20 getchar();21 }22 return 0;23}
結(jié)果如下
任務(wù)一:XML與YAML的文件寫入
任務(wù)二:XML與YAML的文件寫入
步驟:
第一步:XML、YAML文件的打開
在Opencv中澄者,使用FileStorage進(jìn)行文件讀寫笆呆。XML文件操作與YAML一樣请琳,不過存在一些細(xì)小差別。
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);
文檔打開后很關(guān)心的一件事就是赠幕,進(jìn)行確認(rèn)是否成功俄精。FileStorage有自己的成員函數(shù)返回文件打開狀態(tài):
1// bool FileStorage::isOpened() const; 2if ( !fs.isOpened() ) // failed 3{ 4 cout<<"Save File Failed!"<<endl; 5 return ; 6} 7else // succeed 8{ 9 ...10}
第二步:進(jìn)行文件讀寫操作
FileStorage文件讀與寫的方法與C++語言中的文件流對象的使用很像,對>>和<<進(jìn)行了重載榕堰,分別用于文件讀取和寫入竖慧。很棒的是,F(xiàn)ileStorage支持一些常用格式的直接讀寫逆屡,例如字符圾旨、字符串、數(shù)字魏蔗、cv::Mat等砍的。對于不支持的數(shù)據(jù)結(jié)構(gòu),只能按照規(guī)則自己去寫啦~
1fs << "frameCount" << 5; // 字符和數(shù)字2Mat_<double> cameraMat = Mat_<double>::zeros(3, 3); 3fs << "Camera Intrinsic Matrix" << cameraMat;
注意:
- fs << "frameCount" <<5中""內(nèi)輸出的字符串是有限制的莺治,對于YAML有效范圍是:[a-z]廓鞠,[A-Z],[0-9]谣旁,”-“床佳,”_”和空格。XML與YAML基本一致榄审,但是YAML字符之間加空格是允許的夕土,XML不允許。如果出現(xiàn)以下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.(數(shù)組和maps)
Read and write your own data structures.(你自己的數(shù)據(jù)類型)
具體查考:
https://docs.opencv.org/master/dd/d74/tutorialfileinputyml.htmlwithxmlyml.html
第三步:文件關(guān)閉
fs.release();
寫入XML或YAML文件
代碼如下
1//---------------------------------【頭文件角溃、命名空間包含部分】------------------------------- 2// 描述:包含程序所使用的頭文件和命名空間 3//------------------------------------------------------------------------------------------------ 4#include "opencv2/opencv.hpp" 5#include <time.h> 6using namespace cv; 7//-----------------------------------【main( )函數(shù)】-------------------------------------------- 8// 描述:控制臺(tái)應(yīng)用程序的入口函數(shù)拷获,我們的程序從這里開始 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文件讀寫完畢,請?jiā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運(yùn)算符> > 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操作符很容易的讀數(shù)值陣列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 //程序結(jié)束驮吱,輸出一些幫助文字43 printf("\n文件讀取完畢,請輸入任意鍵結(jié)束程序~");44 getchar();45 return 0;46}
FileNode類的API網(wǎng)址:
https://docs.opencv.org/master/de/dd9/classcv11FileNode.html
如果不懂的話萧吠,QQ或者微信公眾號(hào)通知一聲左冬。
1.寫操作效果圖
2.讀操作效果圖
本人是抱著玩一玩的心態(tài),學(xué)習(xí)opencv(其實(shí)深度學(xué)習(xí)沒有外界說的這么高深纸型,小嗷是白板拇砰,而且有工作在身并且于代碼無關(guān))
大家可以把我的數(shù)學(xué)水平想象成初中水平梅忌,畢竟小嗷既不是代碼靠吃飯又不是靠數(shù)學(xué)吃飯,畢業(yè)N年
寫文章主要是為了后人少走點(diǎn)彎路除破,多交點(diǎn)朋友牧氮,一起學(xué)習(xí)
如果有好的圖像識(shí)別群拉我進(jìn)去QQ:631821577
就我一個(gè)白板,最后還是成的瑰枫,你們別怕踱葛,慢慢來把
分享可以無數(shù)次,轉(zhuǎn)載成自己文章QQ郵箱通知一下光坝,未經(jīng)授權(quán)請勿轉(zhuǎn)載尸诽。
QQ群:736854977
有什么疑問公眾號(hào)提問,下班或者周六日回答教馆,ths
API文檔:opencv2refman.pdf(Ctrl + F查找相關(guān)bitwise_and()逊谋,就會(huì)有它的定義和各個(gè)參數(shù)意思)
密碼:ev4g
推薦文章: