1
|
|
|
# -*- coding: utf-8 -* |
2
|
|
|
import numpy as np |
3
|
|
|
import os |
4
|
|
|
import matplotlib.image as mpimg |
5
|
|
|
from scipy import misc |
6
|
|
|
import argparse |
7
|
|
|
|
8
|
|
|
# initialize parameters |
9
|
|
|
parser = argparse.ArgumentParser(description='PCA ORL') |
10
|
|
|
parser.add_argument('--image-scale', type=float, default=0.5, metavar='scale', |
11
|
|
|
help='scale rate for image (default: 0.5)') |
12
|
|
|
parser.add_argument('--train-per-person', type=int, default=4, metavar='k', |
13
|
|
|
help='training number per-person minimal to 1, maximum to 9 (default: 4)') |
14
|
|
|
parser.add_argument('--print-feature-face', type=bool, default=False, metavar='feature_face', |
15
|
|
|
help='print feature face (default: False)') |
16
|
|
|
parser.add_argument('--principal-rate', type=float, default=1, metavar='principal_percent', |
17
|
|
|
help='random seed (default: 1)') |
18
|
|
|
args = parser.parse_args() |
19
|
|
|
|
20
|
|
|
scale = args.image_scale |
21
|
|
|
k = args.train_per_person |
22
|
|
|
feature_face = args.print_feature_face |
23
|
|
|
principal_percent = args.principal_rate |
24
|
|
|
|
25
|
|
|
# covert image to sole vector |
26
|
|
|
def img2vector(filename): |
27
|
|
|
imgVector = misc.imresize(mpimg.imread(filename), scale).flatten() |
28
|
|
|
return imgVector.astype(np.float) |
29
|
|
|
|
30
|
|
|
# load image from diretion |
31
|
|
|
def loadimage(dataSetDir): |
32
|
|
|
train_face = np.zeros((40 * k, int(112 * scale) * int(92 * scale))) # image size:112*92 |
33
|
|
|
train_face_number = np.zeros(40 * k).astype(np.int8) |
34
|
|
|
test_face = np.zeros((40 * (10 - k), int(112 * scale) * int(92 * scale))) |
35
|
|
|
test_face_number = np.zeros(40 * (10 - k)).astype(np.int8) |
36
|
|
|
for i in np.linspace(1, 40, 40).astype(np.int8): #40 sample people |
37
|
|
|
people_num = i |
38
|
|
|
for j in np.linspace(1, 10, 10).astype(np.int8): #everyone has 10 different face |
39
|
|
|
if j <= k: |
40
|
|
|
filename = dataSetDir+'/s'+str(people_num)+'/'+str(j)+'.pgm' |
41
|
|
|
img = img2vector(filename) |
42
|
|
|
train_face[(i-1)*k+(j-1),:] = img |
43
|
|
|
train_face_number[(i-1)*k+(j-1)] = people_num |
44
|
|
|
else: |
45
|
|
|
filename = dataSetDir+'/s'+str(people_num)+'/'+str(j)+'.pgm' |
46
|
|
|
img = img2vector(filename) |
47
|
|
|
test_face[(i-1)*(10-k)+(j-k)-1,:] = img |
48
|
|
|
test_face_number[(i-1)*(10-k)+(j-k)-1] = people_num |
49
|
|
|
|
50
|
|
|
return train_face,train_face_number,test_face,test_face_number #tuple |
51
|
|
|
|
52
|
|
|
# subtract a vector from a matrex |
53
|
|
|
def subvector(target_matrix, target_vector): |
54
|
|
|
vector4matrix = np.repeat(target_vector, target_matrix.shape[0],axis = 0) |
55
|
|
|
target_matrix = target_matrix - vector4matrix |
56
|
|
|
return target_matrix |
57
|
|
|
|
58
|
|
|
# both data subtract mean data of train data |
59
|
|
|
def submean(train_data, test_data): |
60
|
|
|
mean_data = train_data.mean(axis = 0).reshape(1, train_data.shape[1]) |
61
|
|
|
train_data = subvector(train_data, mean_data) |
62
|
|
|
test_data = subvector(test_data, mean_data) |
63
|
|
|
return train_data,test_data |
64
|
|
|
|
65
|
|
|
# main program |
66
|
|
|
train_face,train_face_number,test_face,test_face_number = loadimage(os.getcwd()+'/att_faces') |
67
|
|
|
train_face, test_face = submean(train_face, test_face) |
68
|
|
|
|
69
|
|
|
# math calculate: the relevant mathematical formula can be found in the doc document |
70
|
|
|
# build high-dimensional space |
71
|
|
|
cov = np.dot(train_face.T, train_face) |
72
|
|
|
# calculate eigenvalues & eigenvectors |
73
|
|
|
l, v = np.linalg.eig(cov) |
74
|
|
|
# sort eigenvectors by the value of eigenvalues |
75
|
|
|
mix = np.vstack((l,v)) |
76
|
|
|
mix = mix.T[np.lexsort(mix[::-1,:])].T[:,::-1] |
77
|
|
|
v = np.delete(mix, 0, axis = 0) |
78
|
|
|
|
79
|
|
|
# select the principal components and map face images into high dimensional space |
80
|
|
|
v = v[:,0:int(v.shape[1]*principal_percent)] |
81
|
|
|
train_face = np.dot(train_face, v) |
82
|
|
|
test_face = np.dot(test_face , v) |
83
|
|
|
|
84
|
|
|
# recognise via measuring educlidean distance in high dimentional space |
85
|
|
|
count = 0 |
86
|
|
|
for i in np.linspace(0, test_face.shape[0] - 1, test_face.shape[0]).astype(np.int64): |
87
|
|
|
sub = subvector(train_face,test_face[i, :].reshape((1,test_face.shape[1]))) |
88
|
|
|
dis = np.linalg.norm(sub, axis = 1) |
89
|
|
|
fig = np.argmin(dis) |
90
|
|
|
if train_face_number[fig] == test_face_number[i]: |
91
|
|
|
count = count + 1 |
92
|
|
|
correct_rate = count / test_face.shape[0] |
93
|
|
|
|
94
|
|
|
# show the parameters and results |
95
|
|
|
print("Principal rate=", principal_percent * 100, "%, count for", int(v.shape[1]*principal_percent), "principal eigenvectors") |
96
|
|
|
print("Correct rate =", correct_rate * 100 , "%") |
97
|
|
|
|
98
|
|
|
#show feature maps |
99
|
|
|
if feature_face == True: |
100
|
|
|
import matplotlib.pyplot as plt |
101
|
|
|
plt.figure('Feature Maps') |
102
|
|
|
r, c = (4, 10) |
103
|
|
|
for i in range(r * c): |
104
|
|
|
plt.subplot(r,c,i+1) |
105
|
|
|
plt.imshow(v[:, i].real.reshape(int(112 * scale), int(92 * scale)), cmap='gray') |
106
|
|
|
plt.axis('off') |
107
|
|
|
plt.show() |