OpenCV學習(36) 人臉識別(1)


本文主要參考OpenCV人臉識別教程:http://docs.opencv.org/modules/contrib/doc/facerec/facerec_tutorial.html

1、OpenCV 從2.4開始支持3個新的人臉識別算法。

    1. Eigenfaces 極值特征臉 createEigenFaceRecognizer()
    2. Fisherfaces createFisherFaceRecognizer()
    3. Local Binary Patterns Histograms局部二值直方圖 createLBPHFaceRecognizer()

2、為了使用這三種算法,我們首先需要准備人臉訓練樣本,本文采用AT&T Facedatabase(點擊下載)提供的人臉訓練樣本,該樣本包括40個人,每人10張照片。照片在不同時間、不同光照、不同表情(睜眼閉眼、笑或者不笑)、不同人臉細節(戴眼鏡或者不戴眼鏡)下采集。所有的圖像都在一個黑暗均勻的背景下,正面豎直人臉(有些有輕微旋轉)。圖像格式為pgm,圖像大小為92*112,我們可以用gimp打開該格式的圖像。

     解壓AT&T人臉數據庫后,我們把目錄att_faces拷貝到solution文件目錄。在att_faces目錄中,有s1,s2,...s40,共40個子目錄,每個子目錄中有1.pgm...10.pgm,10個文件,每個子目錄對應一個人,子目錄中的每副照片,對應一個人的各種人臉表情。比如s1中存放的10張人臉樣本如下所示:

imageimageimageimageimageimageimageimageimageimage

      下面我們我們創建一個txt文件facerec_at.txt,格式如下,每一行包括兩個字段,中間用“;”分開,第一個字段表示樣本圖片的路徑文件名,第二個參數是一個整數索引,表示第幾個人,例如第二個參數都為0,則表示第一個人,后面依次類推:

../att_faces/s13/2.pgm;12
../att_faces/s13/7.pgm;12
../att_faces/s13/6.pgm;12
../att_faces/s13/9.pgm;12
../att_faces/s13/5.pgm;12
../att_faces/s13/3.pgm;12
../att_faces/s13/4.pgm;12
../att_faces/s13/10.pgm;12
../att_faces/s13/8.pgm;12
../att_faces/s13/1.pgm;12
../att_faces/s17/2.pgm;16
../att_faces/s17/7.pgm;16

...

../att_faces/s38/10.pgm;37
../att_faces/s38/8.pgm;37
../att_faces/s38/1.pgm;37

3. Eigenfaces算法描述:

      二維灰度圖像p*q大小,是一個m=pq維的向量空間,一個100*100像素大小的圖像就是10000維的圖像空間。我們可以通過主成分分析算法(PCA)來對m維的圖像向量進行降維操作。OpenCV中PCA算法細節,可以參考:http://www.cnblogs.com/mikewolf2002/p/3432243.html,通過PCA算法,我們可以得到k個特征臉,k就是我們選擇降到的維數。

算法描述Algorithmic Description

1348661752_2689  表示一個隨機特征,其中 1348661752_6394 .

  1. 計算均值向量 1348661752_2047

1348661752_5619

  1. 計算協方差矩陣 S

1348661765_8882

  1. 計算 的特征值1348661765_1659    和對應的特征向量   1348661765_8011 1348661765_7365
  1. 對特征值進行遞減排序,特征向量和它順序一致. k個主成分也就是k個最大的特征值對應的特征向量。

x的K個主成份:

1348661765_6154

其中1348661776_6981  .

PCA基的重構:

1348661776_4408

其中 1348661776_3871 .

然后特征臉通過下面的方式進行人臉識別:

  1. 把所有的訓練數據投影到PCA子空間
  2. 把待識別圖像投影到PCA子空間
  3. 找到訓練數據投影后的向量和待識別圖像投影后的向量最近的那個。

4. 程序開始后,我們把樣本圖像和索引標簽讀到兩個vector變量中。

    // 得到txt文件的名字
    string fn_csv = string("facerec_at_t.txt");
    // 定義一個Mat格式的vector用來保存圖像,int格式的vector表示圖像索引標簽
    vector<Mat> images;
    vector<int> labels;
    //讀入圖像文件和索引標簽
    try {
        read_csv(fn_csv, images, labels);
        } catch (cv::Exception& e)
        {
            cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
            exit(1);
        }
    我們選擇images中的最后一副圖片,作為檢測的圖像,並把它從images中移除。

Mat testSample = images[images.size() - 1];
int testLabel = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();

通過下面的代碼,我們輸入待檢測的圖像,返回結果是對應人的索引標簽,我們輸入圖像是第37個人,從結果看是對的。

    //創建特征臉算法模型,並通過樣本訓練數據
    Ptr<FaceRecognizer> model = createEigenFaceRecognizer();
    model->train(images, labels);

    //通過predict輸入待檢測的圖像,返回結果是索引標簽
    int predictedLabel = model->predict(testSample);
    string result_message = format("Predicted class = %d / Actual class = %d.", predictedLabel, testLabel);
    cout << result_message << endl;

image

5. 通過下面的代碼,我們可以求得特征值和特征向量值,並把特征向量顯示為特征臉。

// 特征值和特征向量
Mat eigenvalues = model->getMat("eigenvalues");
// And we can do the same to display the Eigenvectors (read Eigenfaces):
Mat W = model->getMat("eigenvectors");
//特征值列數是1,行數是特征值的數量399
//特征向量10304*399,每一列都是一個特征向量
//每一個特征值對應一個特征向量

printf("特征值數量 :%d\n", eigenvalues.rows);
printf("特征向量維數 :%d\n",W.rows);

//顯示10個特征向量
for (int i = 0; i < min(10, W.cols); i++)
    {
    string msg = format("Eigenvalue #%d = %.5f", i, eigenvalues.at<double>(i));
    cout << msg << endl;
   // 得到第i個特征向量
    Mat ev = W.col(i).clone();
    // 把特征向量歸一化到0-255,便於顯示
    Mat grayscale = toGrayscale(ev.reshape(1, height));
    // 用Jet colormap顯示灰度圖.
    imshow(format("gray image%d", i), grayscale);
    Mat cgrayscale;
    applyColorMap(grayscale, cgrayscale, COLORMAP_JET);
    imshow(format("%d", i), cgrayscale);
    }

我們總共顯示了10個特征向量(特征臉),第一個特征臉的灰度圖和color map圖如下:

imageimage

程序代碼:工程FirstOpenCV31

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM