python人脸识别理论_人脸识别算法-特征脸方法(Eigenface)及python实现,eigenfacepython,特征脸方法基本是将人脸识...

人脸识别算法-特征脸方法(Eigenface)及python实现,eigenfacepython,特征脸方法基本是将人脸识

这几天无聊,正好想起来以前谁说有同学做人脸识别,感觉好高大上,所以找来一些基础的人脸识别算法来自己实现一下,正好锻炼一下numpy的使用。

特征脸方法基本是将人脸识别推向真正可用的第一种方法,了解一下还是很有必要的。特征脸用到的理论基础PCA我在这里就不说了,百度一大堆,主要讲一下实现步骤和自己在用python实现是发现的问题。这里我所使用的训练图片是YALE的人脸数据库点击打开链接,这里面有15位志愿者的165张图片,包含光照,表情和姿态的变化。(我们做实验的时候就会发现,特征脸算法对光照敏感。)在unpadded文件夹下。每张图片的尺寸是98*116。

2ddb2ca263e7a4d0b1128bf61c69dad6.jpeg

特征脸实现步骤(大家如果英语好可以看看这个点击打开链接):

1.获取包含M张人脸图像的集合

8248fc252a3d8585dd6fdf8aecadfcb4.png。我们这里使用15张xxx.normal.pgm来作为人脸训练图像,所以这里M=15.我们把导入的图像拉平,

本来是98*116的矩阵,我们拉平也就是一个11368*1的矩阵,然后M张放在一个大矩阵下,该矩阵为11368*15。

2.我们计算平均图像

bd1b649e158964d6f674dedc056601d1.png,并获得偏差矩阵

6a777f0b423ffff855cd43bac13e10f2.png。为11368*15.平均图像也就把每一行的15个元素平均计算,

这样最后的平均图像就是一个我们所谓的大众脸。然后每张人脸都减去这个平均图像,最后得到。

96ef4e952c6ca97daf5fce4267405e05.png

28abc491b65fdf6721dfa53ae03bd01d.jpeg

3.求得的协方差矩阵。并计算的特征值和特征向量。这是标准的PCA算法流程。但是在这里一个很大的问题就是,协方差矩阵的维度会大到无法计算,例如我们这个11368*15的矩阵,它的协方差矩阵是11368*11368,这个计算量非常大,而且储存也很困难,所以有大神推导出了下面的方法:

设 T 是预处理图像的矩阵,每一列对应一个减去均值图像之后的图像。则,协方差矩阵为 S = TTT ,并且对 S 的特征值分解为

d2728573d7f48e2d7c4dc9cba91aefc2.png

然而, TTT 是一个非常大的矩阵。因此,如果转而使用如下的特征值分解

fdda1325f47dbddf4d99582767926784.png

此时,我们发现如果在等式两边乘以T,可得到

99b24834e21691c7cc961326640dd7ad.png

这就意味着,如果 ui 是 TTT的一个特征向量,则 vi = Tui 是 S 的一个特征向量。

看懂上面这一些需要一些线性代数知识,这里的T 就是上面的偏差矩阵, 反正到最后我们得TTT的一个特征向量,再用T与之相乘就是协方差矩阵的特征向量

eee853679b635ba5b34e9d719651bf3c.png。而此时我们求的特征向量是11368*15的矩阵,每一行(11368*1)如果变成图像大小矩阵(98*116)的话,都可以看做是一个新人脸,被称为特征脸。这里展现我试验中的其中一部分。

d28eb268de3c1eddc937cc28c7dfb728.jpeg

4.主成分分析。在求得的特征向量和特征值中,越大的特征值对于我们区分越重要,也就是我们说的主成分,我们只需要那些大的特征值对应的特征向量,而那些十分小甚至为0的特征值对于我们来说,对应的特征向量几乎没有意义。在这里我们通过一个阈值selecthr来控制,当排序后的特征值的一部分相加大于该阈值时,我们选择这部分特征值对应的特征向量,此时我们剩下的矩阵是11368*M’,M’根据情况在变化。 这样我们不仅减少了计算量,而且保留了主成分,减少了噪声的干扰。

5.这一步就是开始进行人脸识别了。此时我们导入一个新的人脸,我们使用上面主成分分析后得到的特征向量

af12957a9be612267faa24e5b15ce4f0.png,来求得一个每一个特征向量对于导入人脸的权重向量

12dd6cc7b0de763eb2135c0c120059ab.jpeg

42f952cb045ea0fc77dea7b9d11b9bea.png

这里的

fb319a1f04ef2fad73c15c3b0c4fa210.png就是上面第2步求得的平均图像。 特征向量其实就是训练集合的图像与均值图像在该方向上的偏差,通过未知人脸在特征向量的投影,我们就可以知道未知人脸与平均图像在不同方向上的差距。此时我们用上面第2步我们求得的偏差矩阵的每一行做这样的处理,每一行都会得到一个权重向量。我们利用求得

d0fea39207646957d621f5a80f568446.jpeg

d18680f1cb73ab1b7babcf9b6f714794.jpeg的欧式距离来判断未知人脸与第k张训练人脸之间的差距。

d9273c92a2da18c1a00b33a4767bfbfd.png

在这里因为我假设我要识别的未知人肯定是训练集合里有的,所以我通过比较

e4225ea6c2590553f9ae5ba02ea4b62a.jpeg,选择最小的k就是这个人脸对应的训练集合的脸。实际上,一般都是设定距离阈值,当距离小于阈值时说明要判别的脸和训练集内的第k个脸是同一个人的。当遍历所有训练集都大于阈值时,根据距离值的大小又可分为是新的人脸或者不是人脸的两种情况。根据训练集的不同,阈值设定并不是固定的。

最后附上python代码,这里的 ReconginitionVector函数就是求得特征向量的函数,就是按照上面说的顺序写下来的,judgeFace函数用来识别人脸。(大家可以借鉴一下,如果发现有什么不对的欢迎讨论):

Python

#coding:utf-8

from numpy import *

from numpy import linalg as la

import cv2

import os

def loadImageSet(add):

FaceMat = mat(zeros((15,98*116)))

j =0

for i in os.listdir(add):

if i.split('.')[1] == 'normal':

try:

img = cv2.imread(add+i,0)

except:

print 'load %s failed'%i

FaceMat[j,:] = mat(img).flatten()

j += 1

return FaceMat

def ReconginitionVector(selecthr = 0.8):

# step1: load the face image data ,get the matrix consists of all image

FaceMat = loadImageSet('D:\python/face recongnition\YALE\YALE\unpadded/').T

# step2: average the FaceMat

avgImg = 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 = linalg.eig(mat(diffTrain.T*diffTrain))

eigSortIndex = argsort(-eigvals)

for i in xrange(shape(FaceMat)[1]):

if (eigvals[eigSortIndex[:i]]/eigvals.sum()).sum() >= selecthr:

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):

diff = judgeImg.T - avgImg

weiVec = FaceVector.T* diff

res = 0

resVal = inf

for i in range(15):

TrainVec = FaceVector.T*diffTrain[:,i]

if (array(weiVec-TrainVec)**2).sum() < resVal:

res = i

resVal = (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 = 'D:\python/face recongnition\YALE\YALE\unpadded\subject'+nameList[i]+'.'+c+'.pgm'

judgeImg = cv2.imread(loadname,0)

if judgeFace(mat(judgeImg).flatten(),FaceVector,avgImg,diffTrain) == int(nameList[i]):

count += 1

print 'accuracy of %s is %f'%(c, float(count)/len(nameList)) # 求出正确率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值