-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpart1.py
More file actions
151 lines (113 loc) · 3.7 KB
/
Copy pathpart1.py
File metadata and controls
151 lines (113 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import numpy as np
import matplotlib.pyplot as plt
import os
from PIL import Image
imageSet = 's5'
# Load all the images of specific set
def load_images(path):
images = []
for file in os.listdir(path):
img = Image.open(os.path.join(path, file)).convert('L') #L -Luinance(balck and white)
images.append(np.array(img)) # Converting images to 2d array
return np.array(images)
faces = load_images('./Data/Dataset/att_faces/'+imageSet)
print("Dataset shape:", faces.shape)
print(f'face = {faces}')
plt.figure(figsize=(6,6))
for i in range(9):
plt.subplot(3,3,i+1)
plt.imshow(faces[i], cmap='gray')
plt.axis('off')
plt.suptitle('Sample Original Faces')
plt.show()
# Converting images into vectors
# X - row : Each data/image,
# X - col : different pixel values of subject in different data
n_samples, h, w = faces.shape
X = faces.reshape(n_samples, h * w)
print("Data matrix shape:", X.shape)
# PCA - Mean centering
mean_face = np.mean(X, axis = 0) # axis = 0 -> operate coloumn-wise : take the mean of each pixel across all images
X_centered = X - mean_face # Determine deviance of each pixel value from the mean (Eg: 133 - 129.3 = 3.7)
# print(f'Mean face = {mean_face}')
# print(f'X = {X}')
# print(f'X_centered = {X_centered}')
# Applying SVD
# Vt = eigenfaces
# S = singular values
# Eigenvalues = S^2/(n-1)
U, S, Vt = np.linalg.svd(X_centered, full_matrices=False)
# print(f'U = {U}')
# print(f'S = {S}')
# print(f'Vt = {Vt}')
# Visualize eigenfaces
plt.figure(figsize=(6,6))
for i in range(9):
plt.subplot(3,3,i+1)
plt.imshow(Vt[i].reshape(h, w), cmap='gray')
plt.axis('off')
plt.suptitle("Top Eigenfaces")
plt.show()
# Reconstruction function the face
def reconstruct_image(x, mean, Vt, k):
return mean + x @ Vt[:k].T @ Vt[:k]
# Comparing the different k values
k_values = [5, 10, 20, 40, 50, 75, 100]
img_index = 0
plt.figure(figsize=(10,8))
for i, k in enumerate(k_values):
recon = reconstruct_image(X_centered[img_index], mean_face, Vt, k)
plt.subplot(3,4,i+1)
plt.imshow(recon.reshape(h,w), cmap='gray')
plt.title(f"k = {k}")
plt.axis('off')
plt.suptitle("Reconstructed Image with Different k")
plt.show()
#------ Analysis -------#
# Function to compute MSE and Compression ratio
data = faces.shape
N = data[1]
d = data[2]
def compute_mse(original, reconstruct_image):
return np.mean((original - reconstruct_image)**2)
def compute_compression_ratio(k):
original_size = N*d
compressed_size = k*(N+d+1)
return original_size / compressed_size
def pca_reconstruct(U, S, Vt, mean_image, k):
"""
Reconstructs image using first k PCA components.
"""
Uk = U[:, :k]
Sk = np.diag(S[:k])
Vk = Vt[:k, :]
X_reconstructed = Uk @ Sk @ Vk + mean_image
return X_reconstructed
# Compute metric for different k
mse_values = []
compression_ratios = []
X_Original = X
for k in k_values:
recon = pca_reconstruct(U, S, Vt, mean_face, k)
mse = compute_mse(X_Original, recon)
cr = compute_compression_ratio(k)
mse_values.append(mse)
compression_ratios.append(cr)
print(f'Mse Values are: {mse_values}')
print(f'Compress ratios = {compression_ratios}')
# MSE Vs Number of Components k
plt.figure()
plt.plot(k_values, mse_values, marker='o')
plt.xlabel("Number of principal components (k)")
plt.ylabel("Mean Squared Error (MSE)")
plt.title("MSE vs Number of Principal Components")
plt.grid(True)
plt.show()
# Compression Ratio vs Number of Components 𝑘
plt.figure()
plt.plot(k_values, compression_ratios, marker='o')
plt.xlabel("Number of principal components (k)")
plt.ylabel("Compression Ratio")
plt.title("Compression Ratio vs Number of Principal Components")
plt.grid(True)
plt.show()