【问题标题】:Principal Component Analysis (PCA) using python使用 python 进行主成分分析 (PCA)
【发布时间】:2013-04-07 18:32:39
【问题描述】:

我正在尝试使用 python 通过主成分分析 (PCA) 实现人脸识别。我正在按照本教程中的步骤操作:http://onionesquereality.wordpress.com/2009/02/11/face-recognition-using-eigenfaces-and-distance-classifiers-a-tutorial/

这是我的代码:

import os
from PIL import Image
import numpy as np
import glob
import numpy.linalg as linalg


#Step1: put database images into a 2D array
filenames = glob.glob('C:\\Users\\Karim\\Downloads\\att_faces\\New folder/*.pgm')
filenames.sort()
img = [Image.open(fn).convert('L').resize((90, 90)) for fn in filenames]
images = np.asarray([np.array(im).flatten() for im in img])


#Step 2: find the mean image and the mean-shifted input images
mean_image = images.mean(axis=0)
shifted_images = images - mean_image


#Step 3: Covariance
c = np.cov(shifted_images)


#Step 4: Sorted eigenvalues and eigenvectors
eigenvalues,eigenvectors = linalg.eig(c)
idx = np.argsort(-eigenvalues)
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]


#Step 5: Only keep the top 'num_eigenfaces' eigenvectors
num_components = 20
eigenvalues = eigenvalues[0:num_components].copy()
eigenvectors = eigenvectors[:, 0:num_components].copy()


#Step 6: Finding weights
w = eigenvectors.T * np.asmatrix(shifted_images)


#Step 7: Input image
input_image = Image.open('C:\\Users\\Karim\\Downloads\\att_faces\\1.pgm').convert('L').resize((90, 90))
input_image = np.asarray(input_image)


#Step 8: get the normalized image, covariance, eigenvalues and eigenvectors for input image
shifted_in = input_image - mean_image
cov = np.cov(shifted_in)
eigenvalues_in, eigenvectors_in = linalg.eig(cov)

我收到一个错误: Traceback (most recent call last): File "C:/Users/Karim/Desktop/Bachelor 2/New folder/new3.py", line 47, in <module> shifted_in = input_image - mean_image ValueError: operands could not be broadcast together with shapes (90,90) (8100)

我尝试从步骤 1 中删除 .flatten(),但这在计算特征值和特征向量时产生了另一个错误: Traceback (most recent call last): File "C:/Users/Karim/Desktop/Bachelor 2/New folder/new3.py", line 25, in <module> eigenvalues,eigenvectors = linalg.eig(c) File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 1016, in eig _assertRank2(a) File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 155, in _assertRank2 'two-dimensional' % len(a.shape)) LinAlgError: 4-dimensional array given. Array must be two-dimensional

我还尝试将.flatten() 添加到第 7 步,但在计算输入图像的特征值和特征向量时还会产生另一个错误: Traceback (most recent call last): File "C:/Users/Karim/Desktop/Bachelor 2/New folder/new3.py", line 49, in <module> eigenvalues_in, eigenvectors_in = linalg.eig(cov) File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 1016, in eig _assertRank2(a) File "C:\Python27\lib\site-packages\numpy\linalg\linalg.py", line 155, in _assertRank2 'two-dimensional' % len(a.shape)) LinAlgError: 0-dimensional array given. Array must be two-dimensional

有人可以帮忙吗??

【问题讨论】:

    标签: python arrays matrix numpy face-recognition


    【解决方案1】:

    我终于看了您提供的教程,似乎作者建议您将图像展平。您现在最好继续使用扁平化数组,因为它与该教程更匹配。

    我相信修复它的地方是在第 7 步,您可以在其中获得输入图像的协方差。但是,输入图像的协方差矩阵将是一个标量,您无法找到它的特征值和特征向量。您可以将其投影为大小为(1,1) 的二维矩阵,但是您的特征值将只是协方差,而特征向量将为[[1]]。

    也就是说,例如,

    In [563]: input_image = np.random.rand(90,90).flatten()
    
    In [564]: c = np.cov(input_image)
    
    In [565]: c
    Out[565]: array(0.08280644230318886)
    
    In [566]: c.shape
    Out[566]: ()
    
    In [567]: c.ndim
    Out[567]: 0
    

    所以我们将c 重塑为二维:

    In [568]: cmat = c.reshape(1,1) # equivalent to cmat = c[...,np.newaxis,np.newaxis]
    
    In [569]: cmat
    Out[569]: array([[ 0.08280644]])
    
    In [570]: cmat.shape
    Out[570]: (1, 1)
    
    In [571]: cmat.ndim
    Out[571]: 2
    

    所以现在我们可以找到特征:

    In [572]: ceigval, ceigvec = linalg.eig(cmat)
    

    但是对于一元矩阵,只有一个特征值和一个特征向量,而特征值是矩阵的元素,特征向量是长度为1的单位向量/恒等式,所以我不确定这个真的是你想做的人脸识别。

    In [573]: ceigval
    Out[573]: array([ 0.08280644])
    
    In [574]: ceigvec
    Out[574]: array([[ 1.]])
    
    In [576]: np.isclose(c, ceigval)
    Out[576]: True
    

    顺便说一句,这就是为什么我们必须制作c 2d:

    In [577]: linalg.eig(c)
    ---------------------------------------------------------------------------
    LinAlgError: 0-dimensional array given. Array must be two-dimensional
    

    另一方面,您可以获得未展平的 input_image 的协方差,然后您将拥有 N 特征值和 N 特征向量:

    In [582]: input_image = np.random.rand(90,90)
    
    In [583]: c = np.cov(input_image)
    
    In [584]: c.shape
    Out[584]: (90, 90)
    
    In [585]: ceigval, ceigvec = linalg.eig(c)
    
    In [586]: ceigval.shape
    Out[586]: (90,)
    
    In [587]: ceigvec.shape
    Out[587]: (90, 90)
    

    【讨论】:

    • 您对输入图像的协方差是正确的。感谢您的有用评论,但老实说,我不明白您将其投影为 2d 矩阵的意思
    • @user2229953 我已经举例说明了。
    猜你喜欢
    • 2013-03-28
    • 2013-03-31
    • 2012-10-24
    • 1970-01-01
    • 2012-11-10
    • 2015-07-29
    • 2013-03-28
    • 2012-11-20
    • 2022-07-06
    相关资源
    最近更新 更多