OpenCV3.3人脸识别模块的API的变化

OpenCV3.3人脸识别模块的API的变化

1. 前言

开始用最新版的OpenCV进行人脸识别的小伙伴也许已经发现了,人脸识别的最新API变化了。这也正是人脸识别等contrib模块没有放到主仓库的原因:不稳定,仍在开发中。当然这次的变化也预示着一些好的事情,毕竟自从OpenCV2.4时期人脸识别模块加入到OpenCV之后就几乎没怎么变过,这次变化说明又有人开始为OpenCV的人脸识别模块贡献代码了。而且还不仅于此,感兴趣的小伙伴可以去github看看OpenCV最新的人脸识别模块的代码,已经加入了人脸关键点检测、人脸对齐的内容,简直是非常让人期待!

其他的都是以后的事情,我们今天先看看人脸识别模块的变化,我们从facerec.hpp来看。

2. opencv3.3之前的facerec.hpp

(提示:代码可以左右滑动查看)

#ifndef __OPENCV_FACEREC_HPP__
#define __OPENCV_FACEREC_HPP__

#include "opencv2/face.hpp"
#include "opencv2/core.hpp"

namespace cv { namespace face {

// base for two classes
class CV_EXPORTS_W BasicFaceRecognizer : public FaceRecognizer
{
public:
    /** @see setNumComponents */
    CV_WRAP virtual int getNumComponents() const = 0;
    // ----------- 此处省略代码若干行 -----------
    // ----------- 此处省略代码若干行 ------------
    // ----------- 此处省略代码若干行 -----------
    CV_WRAP virtual cv::Mat getEigenValues() const = 0;
    CV_WRAP virtual cv::Mat getEigenVectors() const = 0;
    CV_WRAP virtual cv::Mat getMean() const = 0;
};

CV_EXPORTS_W Ptr<BasicFaceRecognizer> createEigenFaceRecognizer(int num_components = 0, double threshold = DBL_MAX);

CV_EXPORTS_W Ptr<BasicFaceRecognizer> createFisherFaceRecognizer(int num_components = 0, double threshold = DBL_MAX);

class CV_EXPORTS_W LBPHFaceRecognizer : public FaceRecognizer
{
public:
    /** @see setGridX */
    CV_WRAP virtual int getGridX() const = 0;
    /** @copybrief getGridX @see getGridX */
    CV_WRAP virtual void setGridX(int val) = 0;
    // ----------- 此处省略代码若干行 -----------
    // ----------- 此处省略代码若干行 ------------
    // ----------- 此处省略代码若干行 -----------
    CV_WRAP virtual cv::Mat getLabels() const = 0;
};

CV_EXPORTS_W Ptr<LBPHFaceRecognizer> createLBPHFaceRecognizer(int radius=1, int neighbors=8, int grid_x=8, int grid_y=8, double threshold = DBL_MAX);

}} //namespace cv::face

#endif //__OPENCV_FACEREC_HPP__

这个文件里要注意的有:

  • 第九行的那句注释:// base for two classes。说明BasicFaceRecognizer是两个类的基类:EigenFaceRecognizer和FisherFaceRecognizer。跟LBPHFaceRecognizer是没啥关系的。即使到了新的API中仍然是这样。

  • 第23、25、40行。创建三种人脸识别器的方法。大致如下,注意第三个和前两个的区别。

    (提示:代码可以左右滑动查看)

    Ptr<BasicFaceRecognizer> model =  createEigenFaceRecognizer();
    Ptr<BasicFaceRecognizer> model =  createFisherFaceRecognizer();
    Ptr<LBPHFaceRecognizer> model  =  createLBPHFaceRecognizer();

3. opencv3.3的facerec.hpp

(提示:代码可以左右滑动查看)

#ifndef __OPENCV_FACEREC_HPP__
#define __OPENCV_FACEREC_HPP__

#include "opencv2/face.hpp"
#include "opencv2/core.hpp"

namespace cv { namespace face {

// base for two classes
class CV_EXPORTS_W BasicFaceRecognizer : public FaceRecognizer
{
public:
    /** @see setNumComponents */
    CV_WRAP int getNumComponents() const;
    // ----------- 此处省略代码若干行 -----------
    // ----------- 此处省略代码若干行 ------------
    // ----------- 此处省略代码若干行 -----------
    CV_WRAP cv::Mat getEigenValues() const;
    CV_WRAP cv::Mat getEigenVectors() const;
    CV_WRAP cv::Mat getMean() const;

    virtual void read(const FileNode& fn);
    virtual void write(FileStorage& fs) const;
    virtual bool empty() const;

    using FaceRecognizer::read;
    using FaceRecognizer::write;

protected:
    int _num_components;
    double _threshold;
    std::vector<Mat> _projections;
    Mat _labels;
    Mat _eigenvectors;
    Mat _eigenvalues;
    Mat _mean;
};

class CV_EXPORTS_W EigenFaceRecognizer : public BasicFaceRecognizer
{
public:
    CV_WRAP static Ptr<EigenFaceRecognizer> create(int num_components = 0, double threshold = DBL_MAX);
};

class CV_EXPORTS_W FisherFaceRecognizer : public BasicFaceRecognizer
{
public:
    CV_WRAP static Ptr<FisherFaceRecognizer> create(int num_components = 0, double threshold = DBL_MAX);
};


class CV_EXPORTS_W LBPHFaceRecognizer : public FaceRecognizer
{
public:
    /** @see setGridX */
    CV_WRAP virtual int getGridX() const = 0;
    // ----------- 此处省略代码若干行 -----------
    // ----------- 此处省略代码若干行 ------------
    // ----------- 此处省略代码若干行 -----------
    CV_WRAP virtual cv::Mat getLabels() const = 0;


    CV_WRAP static Ptr<LBPHFaceRecognizer> create(int radius=1, int neighbors=8, int grid_x=8, int grid_y=8, double threshold = DBL_MAX);
};

}} //namespace cv::face

#endif //__OPENCV_FACEREC_HPP__

我们对比同一个文件的不同时期的内容就可以看出一些变化了。首先需要注意的还是第九行的注释。前面说的同样适用。而且第二个文件的代码看起来更加清晰:EigenFaceRecognizer和FisherFaceRecognizer都是继承自BasicFaceRecognizer。然而LBPHFaceRecognizer跟BasicFaceRecognizer一样,都是继承自FaceRecognizer。

第二个是创建各人脸识别器的代码都同一变成了类的成员函数:create()。所以我们创建人脸识别检测器的时候就要用下面这样的代码了。

(提示:代码可以左右滑动查看)

Ptr<EigenFaceRecognizer> model  = EigenFaceRecognizer::create();
Ptr<FisherFaceRecognizer> model = FisherFaceRecognizer::create();
Ptr<LBPHFaceRecognizer> model   = LBPHFaceRecognizer::create();

4. 以后的人脸识别模块

目前人脸识别模块头文件夹下只有以下三个文件:

bif.hpp
facerec.hpp
predict_collector.hpp

而现在最新的contrib仓库里,人脸识别的头文件夹下,已经是下面这样:

一起期待吧。


知识星球

除了平时发文章之外,也会发一些平时学习过程中其他的参考资料和代码,欢迎加入。

这里写图片描述

已标记关键词 清除标记
``` #include<iostream> #include <opencv2\opencv.hpp> #include <fstream> #include <sstream> #include <opencv2\face\facerec.hpp> #include <windows.h> #include <direct.h> using namespace cv; using namespace std; using namespace face; CascadeClassifier face_cascades; void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') { std::ifstream file(filename, ifstream::in);//c_str()函数可用可不用,无需返回一个标准C类型的字符串 if (!file) { string error_message = "No valid input file was given, please check the given filename."; CV_Error(CV_StsBadArg, error_message); } else { cout << "first ok !" << endl; } string line, path, classlabel; int i = 1; while (getline(file, line))//从文本文件中读取一行字符,未指定限定符默认限定符为“/n” { stringstream liness(line);//这里采用stringstream主要作用是做字符串的分割 getline(liness, path, separator);//读入图片文件路径以分好作为限定符 getline(liness, classlabel);//读入图片标签,默认限定符 if (!path.empty() && !classlabel.empty())//如果读取成功,则将图片和对应标签压入对应容器中 { cout << "second ok!" << i << endl; images.push_back(imread(path, 0)); labels.push_back(atoi(classlabel.c_str())); i++; } } } int main() { String csvPath = "E:\\ORL\\at.txt"; vector<Mat> images; vector<int> labels; read_csv(csvPath, images, labels); //imshow("as", images); imshow("fsed", labels); cout << labels.size() << endl; Ptr<EigenFaceRecognizer> model = EigenFaceRecognizer::create (); //Ptr < BasicFaceRecognizer > model = EigenFaceRecognizer::create(); model->train(images, labels); model->save("E:\\ORL\\PCA_Model.xml"); waitKey(0); system("pause"); return 0; } ``` 运行后两个错误 第一个错误 LNK1120 1 个无法解析的外部命令 Project3 E:\OpenCV project\Project3\x64\Debug\Project3.exe 1 严重性 代码 说明 项目 文件 行 禁止显示状态 第二错误 LNK2019 无法解析的外部符号 "public: static struct cv::Ptr<class cv::face::EigenFaceRecognizer> __cdecl cv::face::EigenFaceRecognizer::create(int,double)" (?create@EigenFaceRecognizer@face@cv@@SA?AU?$Ptr@VEigenFaceRecognizer@face@cv@@@3@HN@Z),该符号在函数 main 中被引用 Project3 E:\OpenCV project\Project3\Project3\源.obj 1
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页