16.物体识别的重要数据文件(XML和YAML文件) --- OpenCV从零开始到图像(人脸 + 物体)识别系列

16.物体识别的重要数据文件(XML和YAML文件) — OpenCV从零开始到图像(人脸 + 物体)识别系列


本文作者:小嗷

微信公众号:aoxiaoji

吹比QQ群:736854977

简书链接:https://www.jianshu.com/u/45da1fbce7d0


本文你会找到以下问题的答案:

  1. 如何使用YAML或XML文件打印和读取文本条目到文件和OpenCV中?
  2. 如何对OpenCV数据结构进行同样的操作?
  3. 如何为您的数据结构做这些?
  4. 使用OpenCV数据结构,如cv::FileStorage, cv::FileNode或cv::FileNodeIterator。

用途:生成数据文件(如下官方自带生成的识别文件)

3.官方xml文件

haarcascade_eye和haarcascade_smile分别代表是眼睛识别和微笑识别的数据文件

4.输入输出XML和YAML文件

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构造函数一共有三个具体情况,视情况而定。

5.FileStorage构造函数

如上图FileStorage构造函数第二个:

参数
filename:要打开的文件的名称或文本字符串来读取数据。
flags:选择操作模式。
encoding:文件的编码。
注意,目前不支持UTF-16 XML编码,您应该使用8位编码而不是它。

flags:操作模式有如下

6.选择模式

读写添加,还有保存在内存缓冲区里,什么格式等等。

(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;
}

结果如下

7.结果如下

7.任务及代码

任务一: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~

8注意结果如下

读取

文件读取的方法有两种:

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

读写还有类型如下

  1. Input and Output of text and numbers.
  2. Input/Output of OpenCV Data structures. (opencv自带Mat)
  3. Input/Output of vectors (arrays) and associative maps.(数组和maps)
  4. 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或者微信通知一声。

5.效果图

1.写操作效果图

9.写操作效果图

2.读操作效果图

10.读操作效果图.PNG

11.总结及感想.png

  1. 本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)
  2. 大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年
  3. 写文章主要是为了后人少走点弯路,多交点朋友,一起学习
  4. 如果有好的图像识别群拉我进去QQ:631821577
  5. 就我一个白板,最后还是成的,你们别怕,慢慢来把

7.二维码

分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。

  • 邮箱:631821577@qq.com
  • QQ群:736854977
  • 有什么疑问公众号提问,下班或者周六日回答,ths
  • API文档:opencv2refman.pdf(Ctrl + F查找相关bitwise_and(),就会有它的定义和各个参数意思)
  • 百度链接:https://pan.baidu.com/s/1xn6cTTZAGSxdAAtrIenhPw
  • 密码:ev4g

推荐文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值