opencv學習之路(40)、人臉識別算法——EigenFace、FisherFace、LBPH

1、人臉識別算法之特徵臉方法(Eigenface)

一、原理介紹及數據收集

特徵臉方法主要是基於PCA降維實現。算法

詳細介紹和主要思想能夠參考數據庫

http://blog.csdn.net/u010006643/article/details/46417127app

上述博客的人臉數據庫打不開了,你們能夠去下面這個博客下載ORL人臉數據庫測試

http://blog.csdn.net/xdzzju/article/details/50445160spa

下載後,ORL人臉數據庫有40我的,每人10張照片。.net

二、流程

三、相關圖示

 

四、代碼

  1 #include <opencv2/opencv.hpp>
  2 #include <opencv2/face.hpp>
  3 
  4 using namespace cv;
  5 using namespace cv::face;
  6 using namespace std;
  7 
  8 //對原圖歸一化
  9 Mat normal(Mat src, Mat dst) {
 10     if (src.channels() == 1)//若原圖單通道
 11         normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
 12     else //不然,原圖三通道
 13         normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
 14     return dst;
 15 }
 16 
 17 void main() {
 18     //讀取文件,轉換爲數據流
 19     string filename = string("at.txt");
 20     ifstream file(filename.c_str(), ifstream::in);
 21     if (!file)
 22         cout << "error" << endl;
 23 
 24     string line, path, classlabel;
 25     vector<Mat>image;
 26     vector<int>labels;
 27     char separator = ';';
 28     while (getline(file,line))
 29     {
 30         stringstream liness(line);
 31         getline(liness, path, separator);
 32         getline(liness, classlabel);
 33         if (!path.empty()&&!classlabel.empty())
 34         {
 35             //cout << "path:" << path<< endl;
 36             image.push_back(imread(path, 0));
 37             labels.push_back(atoi(classlabel.c_str()));
 38         }
 39     }
 40 
 41     if (image.size() < 1 || labels.size() < 1)
 42         cout << "invalid image path..." << endl;
 43 
 44     int height = image[0].rows;
 45     int width = image[0].cols;
 46     //cout << "height:" << height << ",width:" << width<<endl;
 47 
 48     //最後一我的爲測試樣本
 49     Mat testSample = image[image.size() - 1];
 50     int testLabel = labels[labels.size() - 1];
 51     image.pop_back();
 52     labels.pop_back();
 53 
 54     //訓練
 55     Ptr<BasicFaceRecognizer>model = createEigenFaceRecognizer();
 56     model->train(image, labels);
 57 
 58     //識別
 59     int predictLabel = model->predict(testSample);
 60     cout << "actual label:" << testLabel << ",predict label:" << predictLabel << endl;
 61 
 62     //得到特徵值,特徵向量,均值    平均臉
 63     Mat eigenvalues = model->getEigenValues();
 64     Mat eigenvectors = model->getEigenVectors();
 65     Mat mean = model->getMean();
 66     Mat meanFace = mean.reshape(1,height);
 67     Mat dst;
 68     dst= normal(meanFace,dst);
 69     imshow("Mean Face", dst);
 70     
 71     //特徵臉
 72     for (int i = 0; i < min(10,eigenvectors.cols); i++)
 73     {
 74         Mat ev = eigenvectors.col(i).clone();
 75         Mat eigenFace = ev.reshape(1, height);
 76         Mat grayscale;
 77         grayscale = normal(eigenFace, grayscale);
 78         Mat colorface;
 79         applyColorMap(grayscale, colorface, COLORMAP_BONE);
 80         char* winTitle = new char[128];
 81         sprintf(winTitle, "eigenface_%d", i);
 82         imshow(winTitle, colorface);
 83     }
 84 
 85     //重建人臉
 86     for (int num = min(10, eigenvectors.cols); num < min(300, eigenvectors.cols); num+=15)
 87     {
 88         Mat evs = Mat(eigenvectors, Range::all(), Range(0, num));
 89         Mat projection = LDA::subspaceProject(evs, mean, image[0].reshape(1, 1));
 90         Mat reconstruction= LDA::subspaceReconstruct(evs, mean, projection);
 91 
 92         Mat result = reconstruction.reshape(1, height);
 93         reconstruction = normal(result, reconstruction);
 94         char* winTitle = new char[128];
 95         sprintf(winTitle, "recon_face_%d", num);
 96         imshow(winTitle, reconstruction);
 97     }
 98     
 99     waitKey(0);
100 }

2、FisherFace(LDA線性判別分析)

一、理論介紹

http://blog.csdn.net/feirose/article/details/395529973d

 

二、流程

三、PCA和LDA的對比

 

四、代碼(與特徵臉代碼幾乎一致)

此處只列出修改部分code

55行模型訓練    Ptr<BasicFaceRecognizer>model = createFisherFaceRecognizer();

72行顯示特徵臉  for (int i = 0; i < min(16,eigenvectors.cols); i++)
                   Mat ev = eigenvectors.col(i).clone();

86行重建人臉    for (int num = 0; num < min(16, eigenvectors.cols); num++)

3、LBPH

 一、原理介紹

你們能夠參考http://blog.csdn.net/xiaomaishiwoa/article/details/46640377orm

2、流程

三、代碼

#include <opencv2/opencv.hpp>
#include <opencv2/face.hpp>

using namespace cv;
using namespace cv::face;
using namespace std;

//對原圖歸一化
Mat normal(Mat src, Mat dst) {
    if (src.channels() == 1)//若原圖單通道
        normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
    else //不然,原圖三通道
        normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
    return dst;
}

void main() {
    //讀取文件,轉換爲數據流
    string filename = string("at.txt");
    ifstream file(filename.c_str(), ifstream::in);
    if (!file)
        cout << "error" << endl;

    string line, path, classlabel;
    vector<Mat>image;
    vector<int>labels;
    char separator = ';';
    while (getline(file,line))
    {
        stringstream liness(line);
        getline(liness, path, separator);
        getline(liness, classlabel);
        if (!path.empty()&&!classlabel.empty())
        {
            //cout << "path:" << path<< endl;
            image.push_back(imread(path, 0));
            labels.push_back(atoi(classlabel.c_str()));
        }
    }

    if (image.size() < 1 || labels.size() < 1)
        cout << "invalid image path..." << endl;

    int height = image[0].rows;
    int width = image[0].cols;
    //cout << "height:" << height << ",width:" << width<<endl;

    //最後一我的爲測試樣本
    Mat testSample = image[image.size() - 1];
    int testLabel = labels[labels.size() - 1];
    image.pop_back();
    labels.pop_back();

    //訓練
    Ptr<LBPHFaceRecognizer>model = createLBPHFaceRecognizer();
    model->train(image, labels);

    //識別
    int predictLabel = model->predict(testSample);
    cout << "actual label:" << testLabel << ",predict label:" << predictLabel << endl;

    //打印參數
    int radius = model->getRadius();    //中心像素點到周圍像素點的距離
    int neibs = model->getNeighbors();    //周圍像素點的個數
    int grad_x = model->getGridX();        //將一張圖片在x方向分紅幾塊
    int grad_y = model->getGridY();        //將一張圖片在y方向分紅幾塊
    double t = model->getThreshold();    //類似度閾值    
    cout << "radius:" << radius << endl;
    cout << "neibs:" << neibs << endl;
    cout << "grad_x:" << grad_x << endl;
    cout << "grad_y:" << grad_y << endl;
    cout << "threshold:" << t<<endl;
    
    waitKey(0);
}

相關文章
相關標籤/搜索