Eigen Analysis in Face Recognition
- Tung San
- Jun 27, 2022
- 2 min read
Loading Face datasets. Show face examples.
import matplotlib.pyplot as plt
import numpy as np
import scipy.io
allfaces_load = scipy.io.loadmat('./allFaces.mat')
faces = allfaces_load['faces']
dim_1 = int(allfaces_load['m'])
dim_2 = int(allfaces_load['n'])
flatten_faces = np.ndarray.flatten(allfaces_load['nfaces'])
plt.figure(figsize=(15,15))
for i in range(1,4):
img = np.reshape(faces[:,i],(dim_1,dim_2)).T
plt.subplot(1,3,i)
img = plt.imshow(img, cmap='gray')
plt.show()
plt.figure(figsize=(15,15))
for i in range(91,94):
img = np.reshape(faces[:,i],(dim_1,dim_2)).T
plt.subplot(1,3,i-90)
img = plt.imshow(img, cmap='gray')
plt.show()
plt.figure(figsize=(15,15))
for i in range(190,193):
img = np.reshape(faces[:,i],(dim_1,dim_2)).T
plt.subplot(1,3,i-189)
img = plt.imshow(img, cmap='gray')
plt.show()



Prepare training set and test set.
i_trainingindex = 0
i_testindex = 0
i_totalindex = 0
trainingFaces = np.zeros((dim_1*dim_2, 40*36))
testFaces = np.zeros((dim_1*dim_2, 10*36))
y_train = np.zeros(40*36)
y_train = y_train.astype(int)
y_test = np.zeros(10*36)
y_test = y_test.astype(int)
for i in range(36):
trainingFaces[:, i_trainingindex:(i_trainingindex+40)] = faces[:, i_totalindex : (i_totalindex+40)]
testFaces[:, (i_testindex): (i_testindex+10)] = faces[:, (i_totalindex+40):(i_totalindex+40+10)]
y_train[i_trainingindex:(i_trainingindex+40)] = i
y_test[i_testindex:(i_testindex+10)] = i
i_trainingindex = i_trainingindex + 40
i_testindex = i_testindex + 10
i_totalindex = i_totalindex + flatten_faces[i]
print(trainingFaces.shape)
print(testFaces.shape)
print(y_train.shape)
print(y_test.shape)

Calculate the average face and centred faces.
X = trainingFaces
x_avg = np.mean(X, axis=1)
x_avg = np.reshape(x_avg, (-1,1))
print("x_avg:\n", x_avg, "\nshape:\n", x_avg.shape, "\n")
n=X.shape[1]
I_nn=np.eye(n)
I_n=np.ones((n,1))
X_avg = 1/n * X @ I_n @ I_n.T
X_centered = X @ (I_nn- 1/n * I_n @ I_n.T)
print("X_centered:\n", X_centered, "\nshape:\n", X_centered.shape, "\n")

The average face.
plt.figure(figsize=(5,5))
img = np.reshape(x_avg,(dim_1,dim_2)).T
img = plt.imshow(img, cmap='gray')
plt.show()

Centred faces.
plt.figure(figsize=(15,15))
for i in range(1,4):
img = np.reshape(X_centered[:,i],(dim_1,dim_2)).T
plt.subplot(1,3,i)
img = plt.imshow(img, cmap='gray')
plt.show()
plt.figure(figsize=(15,15))
for i in range(91,94):
img = np.reshape(X_centered[:,i],(dim_1,dim_2)).T
plt.subplot(1,3,i-90)
img = plt.imshow(img, cmap='gray')
plt.show()
plt.figure(figsize=(15,15))
for i in range(190,193):
img = np.reshape(X_centered[:,i],(dim_1,dim_2)).T
plt.subplot(1,3,i-189)
img = plt.imshow(img, cmap='gray')
plt.show()



Singular Value Decomposition on the Centred faces.
U, s, V_t = np.linalg.svd(X_centered, full_matrices=0)
S=np.diag(s)
print(U.shape)
print(S.shape)
print(V_t.shape)
Using first 100 Components to represent the original images (project).
U_100 = U[:, :100]
X_projected = U_100.T @ X_centered
X_centered_reconstructed = U_100 @ X_projected
# Using first 100 Components
U_100 = U[:, :100]
X_projected = U_100.T @ X_centered
X_centered_reconstructed = U_100 @ X_projected
A new image (the 1st image in the test dataset)
plt.figure(figsize=(5,5))
img = np.reshape(testFaces[:,0],(dim_1,dim_2)).T
plt.imshow(img, cmap='gray')
plt.show()

Find the 5 closest faces from the training dataset to the 1st face in test dataset.
img = np.reshape(testFaces[:,0], (-1,1))
img_projected = U_100.T @ (img - x_avg)
distance = [np.linalg.norm(img_projected - np.reshape(X_projected[:,i], (-1,1))) for i in range(X_projected.shape[1])]
closest_5_index = np.argsort(distance)[:5]
closest_5 = np.sort(distance)[:5]
print("Closest 5 distances:\n", closest_5)
print("The cloest images from the train dataset to this new image:\n", closest_5_index)

print("5 clostest images from train images:\n")
plt.figure(figsize=(15,15))
for i,index in enumerate(closest_5_index):
img = np.reshape(trainingFaces[:,index],(dim_1,dim_2)).T
plt.subplot(1,5,i+1)
plt.imshow(img, cmap='gray')
print(f"The {i}th image is of class", y_train[index])
plt.show()
print("The new image is actually of class", y_train[0])

Predict all faces in the testing set and evaluate accuracy.
def predict_class(x_new: "an image"):
x_new = np.reshape(x_new, (-1,1))
x_new_projected = U_100.T @ (x_new-x_avg)
distances = [np.linalg.norm(x_new_projected - np.reshape(X_projected[:,i], (-1,1))) for i in range(X_projected.shape[1])]
closest_index = np.argsort(distances)[0]
closest_distance = np.sort(distances)[0]
return y_train[closest_index]
(Test tailor function)
testing = [0, 1, 5, 8, 12, 18, 68, 70, 99, 100, 120]
predicts = [predict_class(testFaces[:,x]) for x in testing]
labels = [y_test[x] for x in testing]
print(predicts)
print(labels)

Overall predictions (the diagonal is the true label, off-diagonal is wrong prediction).
pred = [predict_class(testFaces[:,i]) for i in range(testFaces.shape[1])]
plt.plot(range(testFaces.shape[1]), pred, 'x')
plt.title("prediction")
plt.show()
plt.plot(range(testFaces.shape[1]), y_test, 'x')
plt.title("actual")
plt.show()


Calculate accuracy (the confusion matrix for the 10-first classes is displayed).
conf_mat = np.empty((36,36))
index= [(i,j) for i in range(0, 36) for j in range(0,36)]
for (i,j) in index:
conf_mat[i][j] = sum([act==i and pred==j for act,pred in zip(y_test, pred)])
print("The (i,j)-th entry represents actual==i and predict==j\n")
print("First 10row x First 10col\n", conf_mat[:10,:10])
accuracy = np.trace(conf_mat)/ np.sum(conf_mat)
print("accuracy:\n", accuracy)

Comentarios