top of page

Eigen Analysis in Face Recognition

  • Writer: Tung San
    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


Post: Blog2 Post
bottom of page