采用PCA方法,利用YALE的人脸数据库做人脸识别,15个人,165张图片,每张图片大小为100*100
这里yale文件中是源图片,通过changename.py将名字更改,存放到picture文件下
eigenface具体步骤
1.读取训练所需要的图片,这里使用subjectxx.normal.bmp文件,共15张图片,每张图片拉直为一个(1,100*100)的向量,合并成为一个(15,100*100)的大矩阵
import numpy as np
import cv2
import os
def loadImageSet(add):
FaceMat = np.mat(np.zeros((15,100*100)))
j =0
for i in os.listdir(add):
if i.split('.')[1] == 'normal':
try:
img = cv2.imread(os.path.join(add,i),0)
#0表示读取灰度图
except:
print('load %s failed'%i)
#变成一个向量
j += 1
return FaceMat
2.计算平均矩阵avgImg,得到偏差矩阵diffTrain(以下推导中记偏差矩阵为T)
FaceMat = loadImageSet('picture').T
avgImg = np.mean(FaceMat,1)
diffTrain = FaceMat-avgImg
3.计算协方差矩阵 S=TTT S = T T T ,注意到 T的大小为(100∗100,15) T 的 大 小 为 ( 100 ∗ 100 , 15 ) , S将会巨大(100∗100,100∗100) S 将 会 巨 大 ( 100 ∗ 100 , 100 ∗ 100 ) ,为了避免计算大矩阵特征值,特征向量,采用如下方法。
eigvals,eigVects = np.linalg.eig(np.mat(diffTrain.T*diffTrain))
4.主成分分析
通过上述步骤得到了特征值,但是并不是所有特征值都是必要的,这里从大到小排列,选取i个特征值,i使得前i个特征值加起来,刚好超过所有特征值和的90%
#注意对称阵特征值均为正数,从大到小排列
eigSortIndex = np.argsort(-eigvals)
for i in range(np.shape(FaceMat)[1]):
if (eigvals[eigSortIndex[:i]]/eigvals.sum()).sum() >= 0.9:
#取占比为0.9
eigSortIndex = eigSortIndex[:i]
break
covVects = diffTrain * eigVects[:,eigSortIndex]
上述步骤写成一个函数就是
def ReconginitionVector(selecthr = 0.9):
# step1: load the face image data ,get the matrix consists of all image
FaceMat = loadImageSet('picture').T
# step2: average the FaceMat
avgImg = np.mean(FaceMat,1)
# step3: calculate the difference of avgimg and all image data(FaceMat)
diffTrain = FaceMat-avgImg
#step4: calculate eigenvector of covariance matrix (because covariance matrix will cause memory error)
eigvals,eigVects = np.linalg.eig(np.mat(diffTrain.T*diffTrain))
eigSortIndex = np.argsort(-eigvals)#注意对称阵特征值均为正数,从大到小排列
for i in range(np.shape(FaceMat)[1]):
if (eigvals[eigSortIndex[:i]]/eigvals.sum()).sum() >= selecthr:#取占比为0.9的特征值
eigSortIndex = eigSortIndex[:i]
break
covVects = diffTrain * eigVects[:,eigSortIndex] # covVects is the eigenvector of covariance matrix
# avgImg 是均值图像,covVects是协方差矩阵的特征向量,diffTrain是偏差矩阵
return avgImg,covVects,diffTrain
5.最后实现一个人脸分类问题,通过上述步骤已经得到15张人脸的特征脸,现在利用其它图片对训练结果进行验证。每张测试图片通过计算权重
def judgeFace(judgeImg,FaceVector,avgImg,diffTrain):
#FaceVector是特征向量(100*00,9)
diff = judgeImg.T - avgImg
weiVec = FaceVector.T* diff
res = 0
resVal = np.inf
for i in range(15):
TrainVec = FaceVector.T*diffTrain[:,i]
if (np.array(weiVec-TrainVec)**2).sum() < resVal:
res = i
resVal = (np.array(weiVec-TrainVec)**2).sum()#选出距离最小的一组,就是同一个人
return res+1
6.最后做一个正确率的测试
if __name__ == '__main__':
avgImg,FaceVector,diffTrain = ReconginitionVector(selecthr = 0.9)
nameList = ['01','02','03','04','05','06','07','08','09','10','11','12','13','14','15']
characteristic = ['centerlight','glasses','happy','leftlight','noglasses','rightlight','sad','sleepy','surprised','wink']
for c in characteristic:
count = 0
for i in range(len(nameList)):
# 这里的loadname就是我们要识别的未知人脸图,我们通过15张未知人脸找出的对应训练人脸进行对比来求出正确率
loadname = 'picture\subject'+nameList[i]+'.'+c+'.bmp'
judgeImg = cv2.imread(loadname,0)
if judgeFace(np.mat(judgeImg).flatten(),FaceVector,avgImg,diffTrain) == int(nameList[i]):
count += 1
print('accuracy of %s is %f'%(c, float(count)/len(nameList))) # 求出正确率
全文代码
# -*- coding: utf-8 -*-
"""
Created on Thu Jan 25 17:52:08 2018
@author: 123
"""
import numpy as np
import cv2
import os
def loadImageSet(add):
FaceMat = np.mat(np.zeros((15,100*100)))
j =0
for i in os.listdir(add):
if i.split('.')[1] == 'normal':
try:
img = cv2.imread(os.path.join(add,i),0)#0表示读取灰度图
except:
print('load %s failed'%i)
FaceMat[j,:] = np.mat(img).flatten()#变成一个向量
j += 1
return FaceMat
def ReconginitionVector(selecthr = 0.9):
# step1: load the face image data ,get the matrix consists of all image
FaceMat = loadImageSet('picture').T
# step2: average the FaceMat
avgImg = np.mean(FaceMat,1)
# step3: calculate the difference of avgimg and all image data(FaceMat)
diffTrain = FaceMat-avgImg
#step4: calculate eigenvector of covariance matrix (because covariance matrix will cause memory error)
eigvals,eigVects = np.linalg.eig(np.mat(diffTrain.T*diffTrain))
eigSortIndex = np.argsort(-eigvals)#注意对称阵特征值均为正数,从大到小排列
for i in range(np.shape(FaceMat)[1]):
if (eigvals[eigSortIndex[:i]]/eigvals.sum()).sum() >= selecthr:#取占比为0.9的特征值
eigSortIndex = eigSortIndex[:i]
break
covVects = diffTrain * eigVects[:,eigSortIndex] # covVects is the eigenvector of covariance matrix
# avgImg 是均值图像,covVects是协方差矩阵的特征向量,diffTrain是偏差矩阵
return avgImg,covVects,diffTrain
def judgeFace(judgeImg,FaceVector,avgImg,diffTrain):
#FaceVector是特征向量(100*00,9)
diff = judgeImg.T - avgImg
weiVec = FaceVector.T* diff
res = 0
resVal = np.inf
for i in range(15):
TrainVec = FaceVector.T*diffTrain[:,i]
if (np.array(weiVec-TrainVec)**2).sum() < resVal:
res = i
resVal = (np.array(weiVec-TrainVec)**2).sum()#选出距离最小的一组,就是同一个人
return res+1
if __name__ == '__main__':
avgImg,FaceVector,diffTrain = ReconginitionVector(selecthr = 0.9)
nameList = ['01','02','03','04','05','06','07','08','09','10','11','12','13','14','15']
characteristic = ['centerlight','glasses','happy','leftlight','noglasses','rightlight','sad','sleepy','surprised','wink']
for c in characteristic:
count = 0
for i in range(len(nameList)):
# 这里的loadname就是我们要识别的未知人脸图,我们通过15张未知人脸找出的对应训练人脸进行对比来求出正确率
loadname = 'picture\subject'+nameList[i]+'.'+c+'.bmp'
judgeImg = cv2.imread(loadname,0)
if judgeFace(np.mat(judgeImg).flatten(),FaceVector,avgImg,diffTrain) == int(nameList[i]):
count += 1
print('accuracy of %s is %f'%(c, float(count)/len(nameList))) # 求出正确率