eigenface

eigenface实现人脸识别

采用PCA方法,利用YALE的人脸数据库做人脸识别,15个人,165张图片,每张图片大小为100*100

这里yale文件中是源图片,通过changename.py将名字更改,存放到picture文件下

eigenface_第1张图片

eigenface_第2张图片

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(100100,15) T 的 大 小 为 ( 100 ∗ 100 , 15 ) , S100100,100100) S 将 会 巨 大 ( 100 ∗ 100 , 100 ∗ 100 ) ,为了避免计算大矩阵特征值,特征向量,采用如下方法。

TTTui=TTTTui=S(Tui)=λiuiTλiuiλi(Tui)(1)(2)(3) (1) T T T u i = λ i u i (2) T T T T u i = T λ i u i (3) S ( T u i ) = λ i ( T u i )

即只要计算得到 TTTui T T T 的 特 征 值 u i ,就可以得到 STui S 的 特 征 值 T u i ,而 TTT(15,15) T T T 的 大 小 为 ( 15 , 15 ) ,极大地减小了计算量

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张人脸的特征脸,现在利用其它图片对训练结果进行验证。每张测试图片通过计算权重

Ω=ωk=i=covVects(NewAvg)covVects(FacekAvg)argmink||Ωωk||2(4)(5)(6) (4) Ω = c o v V e c t s ( N e w − A v g ) (5) ω k = c o v V e c t s ( F a c e k − A v g ) (6) i = a r g m i n k | | Ω − ω k | | 2

New是待分类的相片,Face是15种类型的图片
找到距离最小的i就是分类的结果

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)))  # 求出正确率

测试结果展示
eigenface_第3张图片

全文代码

# -*- 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)))  # 求出正确率

你可能感兴趣的:(人脸识别,脸部识别)