利用Python实现基于PCA算法的人脸识别

来源:互联网 发布:c语言基本 编辑:程序博客网 时间:2024/05/16 00:53

        前面文章提到,利用opencv+python组合可以方便提取图像人脸。当然,opencv自带提取算法很大缺陷的,不过并不妨碍我们应用。接下来,利用python已经获许人脸图片进行训练,从而可以识别人脸。本文利用的PCA算法,实现起来较为容易,利用了numpy库。程序还只是一个算法实现,界面和交互都还不太友好,以后我会对其进行改进,并把它扩展为一个可应用的程序。

        详细看代码和注释。

#coding=gbk"""基于PCA算法的人脸识别@author:      jingyiliscut@gmail.com@time:        2012.10"""from PIL import Image, ImageDrawimport numpyimport cvimport osimport sysIMAGE_SIZE = (40,40)def createDatabase(path, number):    """从指定的路径path中处理number个按照顺序命名的人脸图片,成为一个矩阵"""    imageMatrix = []    for i in range(1,number+1):        image = Image.open(path+'\\'+str(i)+'.jpg')        image = image.resize(IMAGE_SIZE) #缩小图片        grayImage = image.convert('L')        imageArray = list(grayImage.getdata())#转换为一个一维数组,按照行排列        imageMatrix.append(imageArray)                    imageMatrix = numpy.array(imageMatrix)  #转换为二维矩阵,行为图像像素值按行排列,没列为一幅图       #print imageMatix        return imageMatrixdef eigenfaceCore(Matrix):    """通过得到的图像矩阵训练特征脸"""    trainNumber, perTotal = numpy.shape(Matrix) #返回图像的个数,和每个图像的大小        """按照列计算平均向量"""    meanArray = Matrix.mean(0) #0按照列计算平均,1按照行计算平均    """计算每个向量与平均向量的差"""    diffMatrix = Matrix - meanArray        """计算协方差矩阵C的替代L"""    #diffMatrixTranspose = numpy.transpose(diffMatrix) #矩阵转置    diffMatrix = numpy.mat(diffMatrix)#创建矩阵类型的数据    L = diffMatrix * diffMatrix.T #使乘得的矩阵较小    eigenvalues, eigenvectors = numpy.linalg.eig(L) #特征向量v[:,i]对应特征值w[i]        """这里得到的特征值和特征向量并无顺序,        下一部按照特征值大于1来提取特征向量"""    eigenvectors = list(eigenvectors.T) #因为特征向量矩阵的每列是一个特征向量,                                        #所以需要转置后,变为一个list,然后通过pop方法,                                        #删除其中的一行,再逆变换转回去    for i in range(0,trainNumber):        if eigenvalues[i] < 1:            eigenvectors.pop(i)                eigenvectors = numpy.array(eigenvectors) #由于无法直接创建一维的矩阵,所以需要一个数组过度    eigenvectors = numpy.mat(eigenvectors).T                     """最后计算特征脸,也就是计算出C        这种变换减少了计算次数"""    #print numpy.shape(diffMatrix)    #print numpy.shape(eigenvectors)     eigenfaces = diffMatrix.T * eigenvectors    return eigenfaces   def recognize(testIamge, Matrix, eigenface):    """testIamge,为进行识别的测试图片    Matrix为所有图片构成的矩阵    eigenface为特征脸       返回识别出的文件的行号"""           """按照列计算平均向量"""    meanArray = Matrix.mean(0) #0按照列计算平均,1按照行计算平均        """计算每个向量与平均向量的差"""    diffMatrix = Matrix - meanArray        """确定经过过滤后的图片数目"""    perTotal, trainNumber = numpy.shape(eigenface)        """将每个样本投影到特征空间"""    projectedImage = eigenface.T * diffMatrix.T        #print numpy.shape(projectedImage)    """预处理测试图片,将其映射到特征空间上"""    testimage = Image.open(testIamge)    testimage = testimage.resize(IMAGE_SIZE)    grayTestImage = testimage.convert('L')    testImageArray = list(grayTestImage.getdata())#转换为一个一维数组,按照行排列    testImageArray = numpy.array(testImageArray)        differenceTestImage = testImageArray - meanArray    #转换为矩阵便于接下来的乘法操作    differenceTestImage = numpy.array(differenceTestImage)    differenceTestImage = numpy.mat(differenceTestImage)        projectedTestImage = eigenface.T * differenceTestImage.T    #print numpy.shape(projectedImage)    #print numpy.shape(projectedTestImage)    """按照欧式距离计算最匹配的人脸"""    distance = []    for i in range(0, trainNumber):        q = projectedImage[:,i]        temp = numpy.linalg.norm(projectedTestImage - q) #计算范数        distance.append(temp)      minDistance = min(distance)    index = distance.index(minDistance)           return index+1 #数组index是从0开始的     if __name__ == "__main__":    TrainNumber = 22    Matrix = createDatabase('D:\FaceRecognition\matlab\PCA_based Face Recognition\PCA_based+Face+Recognition\PCA_based Face Recognition System\TrainDatabase', TrainNumber)    eigenface = eigenfaceCore(Matrix)    unkown = 11    testimage = 'D:\FaceRecognition\matlab\PCA_based Face Recognition\PCA_based+Face+Recognition\PCA_based Face Recognition System\TestDatabase\\' + str(unkown) +'.jpg'        print recognize(testimage, Matrix, eigenface)            

程序可以正确识别出训练集合中的人脸。不过对于更大范围的训练库,还有更进一步的实验还未做。

接下来,我会在人脸识别方面进一步的做算法研究,欢迎有相同兴趣的童鞋一起交流。@Sea_Smile_


转载请注明出处!