close all;
clear clc;

%loading the database
asd = dir('./Cambridge_FaceDB_jpg');

Gamma = zeros(10304, 400);
i = 1;
for j =1:length(asd)
    if strlength(asd(j).name) > 3
        if strcmp(asd(j).name(end-2:end), 'jpg')
            img = imread('Cambridge_FaceDB_jpg/'+ convertCharsToStrings(asd(j).name));
            Gamma(:, i) = reshape(img, 10304, 1);
            i = i + 1;
        end
    end
end
%% 

%deleting a random test image
test_idx = round(400*rand);
test_img = Gamma(:, test_idx);
Gamma(:, test_idx) = [];

%calculating the average image
Psi = mean(Gamma, 2);

%calculating the difference matrix
Psi_matrix = repmat(Psi, 1, 399);
A = Gamma - Psi_matrix;

%PCA-base creation
L = A' * A;
[V, D] = eig(L, 'vector');
[D, idx] = sort(D, 'descend');
V = V(:, idx);
Uraw = A * V;
U = Uraw./vecnorm(Uraw);
K = 50;
U = U(:, 1:K);

%calculating the PCA-projection
Y = U' * A;
Phi = test_img - Psi;
y = U' * Phi;

%selection of the closest PCA-projected train-element
diff = zeros(399, 1);
for k=1:length(diff)
    diff(k) = norm(Y(:, k) - y);
end

[min_value, min_index] = min(diff);

%recontruction of the found element
Phi_rec = U * Y(:, min_index);
rec_test_img = Phi_rec + Psi;

%plotting the original test image
figure(1);
subplot(1, 3, 1);
original = reshape(test_img, 112, 92);
imagesc(uint8(original))
colormap('gray');
title('test');

subplot(1, 3, 2);
avg = reshape(Psi, 112, 92);
imagesc(uint8(avg));
colormap('gray');
title('mean face');

subplot(1, 3, 3);
recognised = reshape(rec_test_img, 112, 92);
imagesc(uint8(recognised));
colormap('gray');
title('reconstructed from the closest PCA-projection, K = 50');


%plotting the first 10 eigenfaces
figure(2);
for l = 1:10
    subplot(2,5,l);
    eigenfaces = reshape(U(:,l), 112, 92);
    imagesc(eigenfaces);
end
colormap('gray');