人脸数据来自http://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
实现代码和效果如下。由于图片数量有限(40*10),将原有图片顺序打乱进行检测。
可见马氏距离效果最佳。
[以下公式和文字来自John Hany的博文 http://johnhany.net/2016/05/from-qr-decomposition-to-pca-to-face-recognition/]
PCA(Principal Component Analysis,主成分分析)
PCA是一种很常用的根据变量协方差对数据进行降维、压缩的方法。它的精髓在于尽量用最少数量的维度,尽可能精确地描述数据。
将PCA用于人脸识别的过程如下:
基于QR分解的PCA算法步骤如下:
进一步,进行人脸识别的过程如下:
距离度量d:
1 #coding:utf8 2 import cv2 3 import numpy as np 4 import matplotlib.pyplot as plt 5 6 def load_img(): 7 img=[] 8 for i in range(40): 9 for j in range(10): 10 path='att_faces\s'+str(i+1)+'\'+str(j+1)+'.pgm' 11 a=cv2.imread(path,0) 12 a=a.flatten()/255.0 13 img.append(a) 14 return img 15 16 def dis(A,B,dis_type=0,s=None): 17 if dis_type==1: # 欧式距离 18 return np.sum(np.square(A-B)) 19 elif dis_type==2: # 马式距离 20 f=np.sqrt(abs(np.dot(np.dot((A-B),s.I),(A-B).T))) # h增大时右侧会出现负值,防止溢出可以s/np.linalg.norm(s) 21 return f.tolist()[0][0] 22 else: # 曼哈顿距离 23 return np.sum(abs(A-B)) 24 25 def pca(data,h,dis_type=0): 26 q,r=np.linalg.qr(data.T) 27 u,s,v=np.linalg.svd(r.T) 28 fi=np.dot(q,(v[:h]).T) 29 y=np.dot(fi.T,data.T) 30 ym=[np.mean(np.reshape(x,(40,10)),axis=1) for x in y] 31 ym=np.reshape(ym,(h,40)) 32 c=[] 33 if dis_type==2:# 计算马氏距离的额外处理" 34 yr=[np.reshape(x,(40,10)) for x in y] 35 yr=[[np.array(yr)[j][k] for j in range(h)]for k in range(40)] 36 for k in yr: 37 k=np.reshape(k,(h,10)) 38 e=np.cov(k) 39 c.append(e) 40 return fi,ym,c 41 42 def validate(fi,ym,test,label,dis_type=0,c=None): 43 ty=np.dot(fi.T,test.T) 44 correctnum=0 45 testnum=len(test) 46 for i in range(testnum): 47 if dis_type==2: 48 n=len(ym.T) 49 dd=[dis(ty.T[i],ym.T[n_],dis_type,np.mat(c[n_])) for n_ in range(n)] 50 else: 51 dd=[dis(ty.T[i],yy,dis_type) for yy in ym.T] 52 if np.argsort(dd)[0]+1==label[i]: 53 correctnum+=1 54 rate = float(correctnum) / testnum 55 print "Correctnum = %d, Sumnum = %d" % (correctnum, testnum), "Accuracy:%.2f" % (rate) 56 return rate 57 58 if __name__ == '__main__': 59 img=load_img() 60 test=img 61 label=[a+1 for a in range(40) for j in range(10)] 62 index=range(400) 63 np.random.shuffle(index) 64 label_=[label[i] for i in index] 65 test_=np.mat([test[i] for i in index]) 66 x_=[2**i for i in range(9)] 67 d_=['Manhattan Distance','Euclidean Metric', 'Mahalanobis Distance'] 68 for j in range(3): 69 y_=[] 70 plt.figure() 71 for i in range(9): 72 fi,ym,c=pca(np.mat(img),h=x_[i],dis_type=j) 73 y_.append(validate(fi,ym,test_,label_,dis_type=j,c=c)) 74 plt.ylim([0,1.0]) 75 plt.plot(x_,y_) 76 plt.scatter(x_,y_) 77 plt.xlabel('h') 78 plt.ylabel('Accuracy') 79 plt.title(d_[j]) 80 plt.show()