1. 程式人生 > >PCA人臉識別學習及C語言實現

PCA人臉識別學習及C語言實現

http://blog.csdn.net/jinshengtao/article/details/18599165

人臉識別主要方法:

  .Eigenfaces,PCA(Principal Component Analysis),Turk and Pentland,1991

  .Fisherfaces,LDA(Linear Discriminant Analysis),Belhumeur, Hespanha and Kriegman,1997

  .LBPH,Local Binary Pattern Histograms,Ahonen, Hadid and Pietikäinen,2004

本文的目的,是結合人臉識別體驗一把PCA,體會其內涵:降維。另外文獻說,PCA的識別效果一般比神經網路ANN好。本文有20張人臉用於訓練,10張人臉用於測試。

訓練樣本和測試樣本來自:http://cswww.essex.ac.uk/mv/allfaces/faces94.zip

1.PCA人臉識別方法

將PCA方法用於人臉識別,其實是假設所有的人臉都處於一個低維線性空間,而且不同的人臉在這個空間中具有可分性。其具體做法是由高維 影象空間經PCA變換後得到一組新的正交基,對這些正交基做一定的取捨,保留其中的一部分生成低維的人臉空間,也即是人臉的特徵子空間。PCA人臉識別演算法步驟包括:

a.人臉影象預處理【我沒做,人臉大小都是高200,寬180】

b.讀入人臉庫,訓練形成特徵子空間 【特徵值、特徵向量的求法,採用我上一篇文章的QR演算法】

c.把訓練影象和測試影象投影到上一步驟中的特徵子空間上 【矩陣相乘】

d.選擇一定的距離函式進行判別  【歐氏距離,挑最小的匹配】

2.PCA人臉識別流程

a.讀入人臉庫,讀入每一個二維的人臉影象並轉化為一維的向量,每個人選定一定數量的人臉照片構成訓練集【共20張】,則訓練集是一個36000*20的矩陣。測試集共10張影象,每次選一張,則測試集是一個36000*1的矩陣。

樣本集:


測試集:


程式碼:

  1. void load_data(double *T,IplImage *src,int k)  
  2. {  
  3.     int i,j;  
  4.     //一副影象壓縮成一維的,存在T的一列裡
  5.     for (i=0;i<IMG_HEIGHT;i++)  
  6.     {  
  7.         for (j=0;j<IMG_WIDTH;j++)  
  8.         {  
  9.             T[(i*IMG_WIDTH+j)*TRAIN_NUM+k-1]= (double)(unsigned char)src->imageData[i*IMG_WIDTH+j];  
  10.         }  
  11.     }  
  12. }  


b.計算 PCA變換的生成矩陣Q。首先計算訓練集的協方差矩陣X,其中x1,x2,...,xn為第i副影象的描述,即xi為一個36000*1的列向量。

由於這個矩陣太大36000*36000,求特徵值和特徵向量比較坑,所以改為求 P=XTX 的特徵向量和特徵值,且有如下性質:

設e是矩陣P的特徵值λ對應的特徵向量,則有:


這裡,X*e也是矩陣Q的特徵值λ對應的特徵向量,可以如此變換。

程式碼:

  1. void calc_mean(double *T,double *m)  
  2. {  
  3.     int i,j;  
  4.     double temp;  
  5.     for (i=0;i<IMG_WIDTH*IMG_HEIGHT;i++)  
  6.     {  
  7.         temp=0;  
  8.         for (j=0;j<TRAIN_NUM;j++)  
  9.         {  
  10.             temp = temp + T[i*TRAIN_NUM+j];  
  11.         }  
  12.         m[i] = temp/TRAIN_NUM;  
  13.     }  
  14. }  
  15. void calc_covariance_matrix(double *T,double *L,double *m)  
  16. {  
  17.     int i,j,k;  
  18.     double *T1;  
  19.     //T = T -m
  20.     for (i=0;i<IMG_WIDTH*IMG_HEIGHT;i++)  
  21.     {  
  22.         for (j=0;j<TRAIN_NUM;j++)  
  23.         {  
  24.             T[i*TRAIN_NUM+j] = T[i*TRAIN_NUM+j] - m[i];  
  25.         }  
  26.     }  
  27.     T1 = (double *)malloc(sizeof(double)*IMG_HEIGHT*IMG_WIDTH*TRAIN_NUM);  
  28.     //L = T' * T
  29.     matrix_reverse(T,T1,IMG_WIDTH*IMG_HEIGHT,TRAIN_NUM);  
  30.     matrix_mutil(L,T1,T,TRAIN_NUM,IMG_HEIGHT*IMG_WIDTH,TRAIN_NUM);  
  31.     free(T1);  
  32. }  

c.計算生成矩陣P的特徵值和特徵向量,並挑選合適的特徵值和特徵向量,構造特徵子空間變化矩陣。這裡P是實對稱矩陣,可以採用上一篇的方法,先進行Household變換將P變成三對角矩陣,然後使用QR迭代演算法求解特徵值和特徵向量,迭代次數60,誤差eps=0.000001,程式碼:
  1. void cstrq(double a[],int n,double q[],double b[],double c[])  
  2. {  
  3.     int i,j,k,u,v;  
  4.     double h,f,g,h2;  
  5.     for (i=0; i<=n-1; i++)  
  6.         for (j=0; j<=n-1; j++)  
  7.         { u=i*n+j; q[u]=a[u];}  
  8.         for (i=n-1; i>=1; i--)  
  9.         { h=0.0;  
  10.         if (i>1)  
  11.             for (k=0; k<=i-1; k++)  
  12.             { u=i*n+k; h=h+q[u]*q[u];}  
  13.             if (h+1.0==1.0)  
  14.             { c[i]=0.0;  
  15.             if (i==1) c[i]=q[i*n+i-1];  
  16.             b[i]=0.0;  
  17.             }  
  18.             else
  19.             { c[i]=sqrt(h);  
  20.             u=i*n+i-1;  
  21.             if (q[u]>0.0) c[i]=-c[i];  
  22.             h=h-q[u]*c[i];  
  23.             q[u]=q[u]-c[i];  
  24.             f=0.0;  
  25.             for (j=0; j<=i-1; j++)  
  26.             { q[j*n+i]=q[i*n+j]/h;  
  27.             g=0.0;  
  28.             for (k=0; k<=j; k++)  
  29.                 g=g+q[j*n+k]*q[i*n+k];  
  30.             if (j+1<=i-1)  
  31.                 for (k=j+1; k<=i-1; k++)  
  32.                     g=g+q[k*n+j]*q[i*n+k];  
  33.             c[j]=g/h;  
  34.             f=f+g*q[j*n+i];  
  35.             }  
  36.             h2=f/(h+h);  
  37.             for (j=0; j<=i-1; j++)  
  38.             { f=q[i*n+j];  
  39.             g=c[j]-h2*f;  
  40.             c[j]=g;  
  41.             for (k=0; k<=j; k++)  
  42.             { u=j*n+k;  
  43.             q[u]=q[u]-f*c[k]-g*q[i*n+k];  
  44.             }  
  45.             }  
  46.             b[i]=h;  
  47.             }  
  48.         }  
  49.         for (i=0; i<=n-2; i++) c[i]=c[i+1];  
  50.         c[n-1]=0.0;  
  51.         b[0]=0.0;  
  52.         for (i=0; i<=n-1; i++)  
  53.         { if ((b[i]!=0.0)&&(i-1>=0))  
  54.         for (j=0; j<=i-1; j++)  
  55.         { g=0.0;  
  56.         for (k=0; k<=i-1; k++)  
  57.             g=g+q[i*n+k]*q[k*n+j];  
  58.         for (k=0; k<=i-1; k++)  
  59.         { u=k*n+j;  
  60.         q[u]=q[u]-g*q[k*n+i];  
  61.         }  
  62.         }  
  63.         u=i*n+i;  
  64.         b[i]=q[u]; q[u]=1.0;  
  65.         if (i-1>=0)  
  66.             for (j=0; j<=i-1; j++)  
  67.             { q[i*n+j]=0.0; q[j*n+i]=0.0;}  
  68.         }