TIPs:
- M就是图片一共多少张;N维向量指图片flatten成一位向量的维数,即
N = 图片高*宽 - 每张图片flatten成列向量,按列排,每一行就是每张图片在某一像素点灰度值/RGB值
- 零均值化后的矩阵维度是
(高*宽,N),如果直接用要用协方差矩阵降维,cov_mat维度(高*宽,高*宽) - 不是对零均值化后的矩阵求特征值和特征向量,是对中心化矩阵的协方差矩阵cov_mat求eig
code:
<pre><code>
eigenface.py
import numpy as np from numpy import linalg as la
def eigenface(imgs):
'''
:param imgs: imgs的维度为MxHxW。即有M张图片,每一张高为H宽为W。
:return: a, b
a: 特征值。 为一维向量。
b: 特征向量。 为二维向量, b[:,i]是特征值a[i]对应的特征向量.
'''
imgs_2d = []
for i in range(0,400):
img_temp = imgs[i,:,:].flatten() #把每张图片flatten,按列放到矩阵imgs_2d里
imgs_2d.append(img_temp)
imgs_2d = np.mat(imgs_2d).T
imgs_mean = np.mean(imgs_2d,axis=1) #对每行求mean,相当于对每个像素点都取mean
imgs_diff = np.mat(imgs_2d) - np.mat(imgs_mean) #对每个像素点零均值化
#a,b = la.eig(imgs_diff.T*imgs_diff) #不是求样本中心化矩阵imgs_diff的特征值,而是求imgs_diff的协方差矩阵的特征值
cov_mat = imgs_diff*imgs_diff.T/400 #求协方差矩阵
a,b = la.eig(cov_mat)
b = np.asarray(b) #最好不要用mat格式,不然会数值溢出
return a, b
</code></pre>
<pre><code>
main.py
from future import division
from future import print_function
import os import numpy as np from pathlib import Path from PIL import Image import matplotlib.pyplot as plt import math from eigen_face import eigenface
def file_abs_path(arg): return Path(os.path.realpath(arg)).parent
def img_show(imgs, H=None, W=None, info=None): imgs = np.asarray(imgs) assert imgs.ndim == 3 M = imgs.shape[0] if H is None: if W is None: H = int(math.sqrt(M)) W = math.ceil(M / H) else: H = math.ceil(M / W) else: if W is None: W = math.ceil(M / H) else: W = max(W, math.ceil(M / H))
plt.figure()
if info is not None:
plt.suptitle(info)
for i in range(M):
plt.subplot(H, W, i+1)
plt.imshow(imgs[i], cmap='gray')
plt.axis('off')
plt.show()
def load_images(): folder_path = file_abs_path(file) image_path = folder_path / 'orl_faces'
img_files = list(image_path.glob('**/*.pgm'))
print('There are {} images in {}'.format(len(img_files), image_path))
imgs = []
for img in img_files:
img_tmp = Image.open(img)
#img_tmp = img_tmp.resize((12, 9), Image.ANTIALIAS) # 因为数据维度比较大,在调试的时候可以去掉这一行的注释,缩放一下图片,这样计算比较快。
img_tmp = np.asarray(img_tmp, dtype=np.float32)
imgs.append(img_tmp)
return np.asarray(imgs)
if name == 'main': imgs = load_images() # 加载图片,imgs的维度为MxHxW。即有M张图片,每一张高为H宽为W。 print(imgs.shape) img_show(imgs[::10], H=5, info='Raw face') # 展示原图 a, b = eigenface(imgs) # 获得特征值 a,特征向量 b.
num = 8
a = a[:num]
N, H, W = imgs.shape
b = b.T.reshape(H*W, H, W)
b = b[:num]
img_show(b, H=2, info='Eigenface')
</code></pre>
- linalg.eig(mat)函数求得的特征值和特征向量已经按照从大到小排列了
- np.shape() ; type() ; np.mat() ; np.asarray() ; np.mean(data,axis=?) ; mat.T
- 最好不要用matrix格式,可能会数值溢出,最好转换成array处理
- 图片等三维数组的理解,要有channel的概念

- 二维矩阵 三维矩阵之间转换☞用reshape函数
- 三维矩阵变二维☞用flatten拉平