Local Binary Patterns Histograms人脸识别

来源:互联网 发布:十个做淘宝九个失败 编辑:程序博客网 时间:2024/05/22 06:05

这里介绍的是用opencv2.4做人脸识别。


数据库下载:

人脸识别中需要质量合格并且经过归一化剪裁过的的灰度图数据库。这里介绍个数据库给大家:http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html。这个数据库称为AT&T Facedatabase,也称为ORL Database of Faces。数据库中的照片是在不同光照,不同时间不同的面部表情和面部细节下照的。数据库中共有40个人,每个人10张不同的照片。


CSV文件的创建:

获取到数据库后,我们需要将数据中程序中图像的路径和对应的标签渠道程序中去以便于训练,这里就需要用到CSV文件。CSV是一种简单的数据交互格式,CSV文件需要包含文件路径,分隔符和标签。例如:at/s1/1.pgm;0。这里“;”是分隔符,标签只要保证同一个人的标签相同即可,并不要求顺序。CSV可以手动自己创建,也可以Python脚本自动生成。对应的脚本为\modules\contrib\doc\facerec\src\create_csv.py。由于我对这个脚本不是很熟悉,所以我的是自己手动创建的。


这里用下面的代码示例说明一下如何进行图像识别:

#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 = "F:/WorkSpace/CPP/FaceRecognition/FaceRecognition/faces.csv";//此处为文件路径。    // 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("\tLBPH(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;}

输出结果如下:


这里分别用到了默认阈值和设阈值的方法。因为设阈值时为0.00,测试样本的距离较远,返回的标签值为-1.这里可以对阈值进行更改。

原创粉丝点击