簡單的特征臉識別實驗
實現特征臉的過程其實就是主成分分析(Principal Component Analysis,PCA)的一個過程。關於PCA的原理問題,它是一種數學降維的方法。是為了簡化問題。在二維的坐標空間內,找到一個單位向量U,使得所有數據在U上的投影之和最大。這樣就能把數據分的盡可能的開。然后把訓練樣本投影到這個向量U上,把測試圖片也投影上去,計算這個投影與各個樣本人臉投影的歐式距離,得出最小的歐式距離的的那個樣本編號,就是最大概率的人臉。
Eigenface算法
特征臉方法(Eigenface)是一個經典算法的人臉識別算法。特征臉方法是從PCA導出的一種人臉識別和描述技術。就是將包含人臉的圖像區域看作是一種隨機向量,因此可以采用K-L變換獲得其正交K-L基底。對應其中較大特征值的基底具有與人臉相似的形狀,因此又稱為特征臉。利用這些基底的線性組合可以描述、表達和逼近人臉圖像,因此可以進行人臉識別與合成。識別過程就是將人臉圖像映射到由特征臉構成的子空間上,比較其與己知人臉在特征空間中的位置,具體步驟如下:
(1) 初始化,獲得人臉圖像的訓練集並計算特征臉,定義為人臉空間,存儲在模板庫中,以便系統進行識別;這里使用Yalefaces數據庫。這里面有15個人,每個人的文件夾中取一張正常狀態的圖像,size為(98,116),並用flatten()把該圖像轉換成一維向量。15張這樣的圖組成一個(8100,15)的矩陣;
(2) 對每一行求均值,得到一個(11368,1)的向量avgImg,這個圖像就是平均臉;
(3) 將圖像矩陣與平均臉相減,得到偏差值diffTrain,用偏差值計算協方差,協方差矩陣C= XXT;
(4) 這里需要做一個變換,因為C算出來為都會非常大,可以改為計算C’,設C’ = XTX,設這里算出的特征向量為E’,XE’= E,這里E就是原本該C得到的特征向量。然后把E歸一化。
人臉識別
這里得到了15個特征臉之后,考慮選擇出主成分。這里取特征向量超過特征向量均值的80%的幾個特征向量,假設是K個,這K個特征向量組成的矩陣設為w。將偏差矩陣轉置乘以w,得到協方差矩陣的特征向量。
(1) 輸入新的人臉圖像,轉換成一維向量,將其映射到特征臉空間,得到一組關於該人臉的特征數據;
(2) 通過檢查圖像與人臉空間的距離判斷它是否是人臉;
(3) 若為人臉,根據權值模式判斷它是否為數據庫中的某個人,並做出具體的操作。
代碼如下:
1 import numpy as np 2 3 from numpy import * 4 5 from numpy import linalg as la 6 7 from PIL import Image 8 9 import glob 10 11 from matplotlib import pyplot as plt 12 13 def loadImageSet(add): 14 15 filenames = glob.glob('face/pgm/*.pgm') 16 17 filenames.sort() 18 19 img = [Image.open(fn).convert('L').resize((98, 116)) for fn in filenames] 20 21 FaceMat = np.asarray([np.array(im).flatten() for im in img]) 22 23 return FaceMat 24 25 def ReconginitionVector(selecthr = 0.8): 26 27 # step1: load the face image data ,get the matrix consists of all image 28 29 FaceMat = loadImageSet('face/yalefaces/') 30 31 print('-----------FaceMat.shape--------') 32 33 print(FaceMat.shape) 34 35 # step2: average the FaceMat 36 37 avgImg = mean(FaceMat,0) 38 39 # step3: calculate the difference of avgimg and all image data(FaceMat) 40 41 diffTrain = FaceMat-avgImg 42 43 covMat =np.asmatrix(diffTrain) * np.asmatrix(diffTrain.T) 44 45 eigvals,eigVects = linalg.eig(covMat) #la.linalg.eig(np.mat(covMat)) 46 47 #step4: calculate eigenvector of covariance matrix (because covariance matrix will cause memory error) 48 49 eigSortIndex = argsort(-eigvals) 50 51 for i in range(shape(FaceMat)[1]): 52 53 if (eigvals[eigSortIndex[:i]]/eigvals.sum()).sum() >= selecthr: 54 55 eigSortIndex = eigSortIndex[:i] 56 57 break 58 59 covVects = diffTrain.T * eigVects[:,eigSortIndex] # covVects is the eigenvector of covariance matrix 60 61 # avgImg 是均值圖像,covVects是協方差矩陣的特征向量,diffTrain是偏差矩陣 62 63 return avgImg,covVects,diffTrain 64 65 def judgeFace(judgeImg,FaceVector,avgImg,diffTrain): 66 67 diff = judgeImg - avgImg 68 69 weiVec = FaceVector.T* diff.T 70 71 res = 0 72 73 resVal = inf 74 75 #============================================================================== 76 77 # plt.imshow(avgImg.reshape(98,116)) 78 79 # plt.show() 80 81 #============================================================================== 82 83 for i in range(15): 84 85 TrainVec = (diffTrain[i]*FaceVector).T 86 87 if (array(weiVec-TrainVec)**2).sum() < resVal: 88 89 res = i 90 91 resVal = (array(weiVec-TrainVec)**2).sum() 92 93 return res+1 94 95 if __name__ == '__main__': 96 97 avgImg,FaceVector,diffTrain = ReconginitionVector(selecthr = 0.8) 98 99 nameList = ['01','02','03','04','05','06','07','08','09','10','11','12','13','14','15'] 100 101 characteristic = ['centerlight','glasses','happy','leftlight','noglasses','rightlight','sad','sleepy','surprised','wink'] 102 103 for c in characteristic: 104 105 count = 0 106 107 for i in range(len(nameList)): 108 109 # 這里的loadname就是我們要識別的未知人臉圖,我們通過15張未知人臉找出的對應訓練人臉進行對比來求出正確率 110 111 loadname = 'face/yalefaces/subject'+nameList[i]+'.'+c+'.pgm' 112 113 judgeImg = Image.open(loadname).convert('L').resize((98, 116)) 114 115 #print(loadname) 116 117 if judgeFace(mat(judgeImg).flatten(),FaceVector,avgImg,diffTrain) == int(nameList[i]): 118 119 count += 1 120 121 print('accuracy of %s is %f'%(c, float(count)/len(nameList))) # 求出正確率
運行結果:
1 accuracy of centerlight is 0.400000 2 3 accuracy of glasses is 0.533333 4 5 accuracy of happy is 0.866667 6 7 accuracy of leftlight is 0.133333 8 9 accuracy of noglasses is 0.800000 10 11 accuracy of rightlight is 0.133333 12 13 accuracy of sad is 0.800000 14 15 accuracy of sleepy is 0.800000 16 17 accuracy of surprised is 0.666667 18 19 accuracy of wink is 0.600000
