zoukankan      html  css  js  c++  java
  • OpenCV学习(40) 人脸识别(4)

    在人脸识别模式类中,还实现了一种基于LBP直方图的人脸识别方法。LBP图的原理参照:http://www.cnblogs.com/mikewolf2002/p/3438698.html

          在代码中,我们只要使用   Ptr<FaceRecognizer> model = createLBPHFaceRecognizer(); 就创建了一个基于LBPH的人脸识别类,其它代码和前面两种人脸识别方法一样。

         在train函数中,会计算每个样本的LBP图像,并求出该图像的二维直方图,把直方图保存在_histograms中,以便在predict函数调用这些直方图进行匹配。

    for(size_t sampleIdx = 0; sampleIdx < src.size(); sampleIdx++)

    {
       // 计算LBP图

        Mat lbp_image = elbp(src[sampleIdx], _radius, _neighbors);
        // 得到直方图
        Mat p = spatial_histogram(
                lbp_image, /* lbp_image */
                static_cast<int>(std::pow(2.0, static_cast<double>(_neighbors))),
    //可能的模式数
                _grid_x, /* grid size x */
                _grid_y, /* grid size y */
                true);
        // 把直方图加到匹配模版中

        _histograms.push_back(p);
    }

    在预测函数中,会先求出输入图像的LBPH图,然后和保存的样本LBPH进行比较,距离最今即为匹配的人脸。


    Mat lbp_image = elbp(src, _radius, _neighbors);
    Mat query = spatial_histogram(
            lbp_image, /* lbp_image */
            static_cast<int>(std::pow(2.0, static_cast<double>(_neighbors))), /* number of possible patterns */
            _grid_x, /* grid size x */
            _grid_y, /* grid size y */
            true /* normed histograms */);
    // 查找最近的匹配者

    minDist = DBL_MAX;
    minClass = -1;
    for(size_t sampleIdx = 0; sampleIdx < _histograms.size(); sampleIdx++)

    {
        double dist = compareHist(_histograms[sampleIdx], query, CV_COMP_CHISQR);
        if((dist < minDist) && (dist < _threshold))

        {
            minDist = dist;
            minClass = _labels.at<int>((int) sampleIdx);
        }
    }


    代码:

    #include "opencv2/core/core.hpp"
    #include "opencv2/contrib/contrib.hpp"
    #include "opencv2/highgui/highgui.hpp"

    #include <iostream>
    #include <fstream>
    #include <sstream>

    using namespace cv;
    using namespace std;

    static void read_csv(const string& filename, vector<Mat>& images, vector<int>& labels, char separator = ';') {
    std::ifstream file(filename.c_str(), ifstream::in);
    if (!file) {
    string error_message = "No valid input file was given, please check the given filename.";
    CV_Error(CV_StsBadArg, error_message);
    }
    string line, path, classlabel;
    while (getline(file, line)) {
    stringstream liness(line);
    getline(liness, path, separator);
    getline(liness, classlabel);
    if(!path.empty() && !classlabel.empty()) {
    images.push_back(imread(path, 0));
    labels.push_back(atoi(classlabel.c_str()));
    }
    }
    }

    int main(int argc, const char *argv[])
    {

    // Get the path to your CSV.
    string fn_csv = string("facerec_at_t.txt");
    // These vectors hold the images and corresponding labels.
    vector<Mat> images;
    vector<int> labels;
    // Read in the data. This can fail if no valid
    // input filename is given.
    try {
    read_csv(fn_csv, images, labels);
    } catch (cv::Exception& e) {
    cerr << "Error opening file "" << fn_csv << "". Reason: " << e.msg << endl;
    // nothing more we can do
    exit(1);
    }
    // Quit if there are not enough images for this demo.
    if(images.size() <= 1) {
    string error_message = "This demo needs at least 2 images to work. Please add more images to your data set!";
    CV_Error(CV_StsError, error_message);
    }
    // Get the height from the first image. We'll need this
    // later in code to reshape the images to their original
    // size:
    int height = images[0].rows;
    // The following lines simply get the last images from
    // your dataset and remove it from the vector. This is
    // done, so that the training data (which we learn the
    // cv::FaceRecognizer on) and the test data we test
    // the model with, do not overlap.
    Mat testSample = images[images.size() - 1];
    int testLabel = labels[labels.size() - 1];
    images.pop_back();
    labels.pop_back();
    // The following lines create an LBPH model for
    // face recognition and train it with the images and
    // labels read from the given CSV file.
    //
    // The LBPHFaceRecognizer uses Extended Local Binary Patterns
    // (it's probably configurable with other operators at a later
    // point), and has the following default values
    //
    // radius = 1
    // neighbors = 8
    // grid_x = 8
    // grid_y = 8
    //
    // So if you want a LBPH FaceRecognizer using a radius of
    // 2 and 16 neighbors, call the factory method with:
    //
    // cv::createLBPHFaceRecognizer(2, 16);
    //
    // And if you want a threshold (e.g. 123.0) call it with its default values:
    //
    // cv::createLBPHFaceRecognizer(1,8,8,8,123.0)
    //
    Ptr<FaceRecognizer> model = createLBPHFaceRecognizer();
    model->train(images, labels);
    // The following line predicts the label of a given
    // test image:
    int predictedLabel = model->predict(testSample);
    //
    // To get the confidence of a prediction call the model with:
    //
    // int predictedLabel = -1;
    // double confidence = 0.0;
    // model->predict(testSample, predictedLabel, confidence);
    //
    string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel);
    cout << result_message << endl;
    // Sometimes you'll need to get/set internal model data,
    // which isn't exposed by the public cv::FaceRecognizer.
    // Since each cv::FaceRecognizer is derived from a
    // cv::Algorithm, you can query the data.
    //
    // First we'll use it to set the threshold of the FaceRecognizer
    // to 0.0 without retraining the model. This can be useful if
    // you are evaluating the model:
    //
    model->set("threshold", 0.0);
    // Now the threshold of this model is set to 0.0. A prediction
    // now returns -1, as it's impossible to have a distance below
    // it
    predictedLabel = model->predict(testSample);
    cout << "Predicted class = " << predictedLabel << endl;
    // Show some informations about the model, as there's no cool
    // Model data to display as in Eigenfaces/Fisherfaces.
    // Due to efficiency reasons the LBP images are not stored
    // within the model:
    cout << "Model Information:" << endl;
    string model_info = format(" LBPH(radius=%i, neighbors=%i, grid_x=%i, grid_y=%i, threshold=%.2f)",
    model->getInt("radius"),
    model->getInt("neighbors"),
    model->getInt("grid_x"),
    model->getInt("grid_y"),
    model->getDouble("threshold"));
    cout << model_info << endl;
    // We could get the histograms for example:
    vector<Mat> histograms = model->getMatVector("histograms");
    // But should I really visualize it? Probably the length is interesting:
    cout << "Size of the histograms: " << histograms[0].total() << endl;
    return 0;
    }

     

    程序代码:工程FirstOpenCV35

     

  • 相关阅读:
    关于数据库主键和外键
    数据库建立索引常用原则
    恭喜!Apache Hudi社区新晋多位Committer
    触宝科技基于Apache Hudi的流批一体架构实践
    轻快好用的Docker版云桌面(不到300M、运行快、省流量)
    实时视频
    通讯-- 通讯录
    通讯-- 总指挥部
    右侧菜单-- 事件面板
    应急救援预案选择逻辑
  • 原文地址:https://www.cnblogs.com/mikewolf2002/p/3438741.html
Copyright © 2011-2022 走看看