最近看到一篇介绍利用“主成份分析实现人脸识别”的matlab应用实例。

学习了一遍,对主成份分析和图像识别有了一个概念性的认识。

这个例子可能是最简单的人脸识别例子了,暂且不考虑实用性,单单起到认识和了解主成份分析法和图像识别的作用。

 

主成分分析法是将原先较多的关联性较强的变量变换为数量较少的互不相关的少数几个综合变量的过程和方法

图像识别,尤其是人脸识别不太可能使用点对点的像素比较实现,某些统一格式的大头照片也会存在瞳距等自然偏差,

因此必须避免直接图片比较。

 

下面matlab程序进行学习注释,希望能帮助记忆。同时加强交流。

程序使用的人脸库来自Essex大学的人脸数据库的face94部分。选择了10个人,每人选择3张照片。1张放入测试集合。

2张放入训练集合。照片比较理想化,绿色背景的大头照片,表情略有不同,光照均匀。

程序的链接如下:

http://www.mathworks.com/matlabcentral/fileexchange/17032-pca-based-face-recognition-system/all_files

内部包含的文件如下

红色的文件是主程序,绿色的是测试集合,蓝色的是训练集合。

license.txt
PCA_based Face Recognition System/CreateDatabase.m
PCA_based Face Recognition System/EigenfaceCore.m
PCA_based Face Recognition System/example.m
PCA_based Face Recognition System/Readme.txt
PCA_based Face Recognition System/Recognition.m
PCA_based Face Recognition System/TestDatabase/1.jpg
PCA_based Face Recognition System/TestDatabase/10.jpg
PCA_based Face Recognition System/TestDatabase/2.jpg
PCA_based Face Recognition System/TestDatabase/3.jpg
PCA_based Face Recognition System/TestDatabase/4.jpg
PCA_based Face Recognition System/TestDatabase/5.jpg
PCA_based Face Recognition System/TestDatabase/6.jpg
PCA_based Face Recognition System/TestDatabase/7.jpg
PCA_based Face Recognition System/TestDatabase/8.jpg
PCA_based Face Recognition System/TestDatabase/9.jpg
PCA_based Face Recognition System/TrainDatabase/1.jpg
PCA_based Face Recognition System/TrainDatabase/10.jpg
PCA_based Face Recognition System/TrainDatabase/11.jpg
PCA_based Face Recognition System/TrainDatabase/12.jpg
PCA_based Face Recognition System/TrainDatabase/13.jpg
PCA_based Face Recognition System/TrainDatabase/14.jpg
PCA_based Face Recognition System/TrainDatabase/15.jpg
PCA_based Face Recognition System/TrainDatabase/16.jpg
PCA_based Face Recognition System/TrainDatabase/17.jpg
PCA_based Face Recognition System/TrainDatabase/18.jpg
PCA_based Face Recognition System/TrainDatabase/19.jpg
PCA_based Face Recognition System/TrainDatabase/2.jpg
PCA_based Face Recognition System/TrainDatabase/20.jpg
PCA_based Face Recognition System/TrainDatabase/3.jpg
PCA_based Face Recognition System/TrainDatabase/4.jpg
PCA_based Face Recognition System/TrainDatabase/5.jpg
PCA_based Face Recognition System/TrainDatabase/6.jpg
PCA_based Face Recognition System/TrainDatabase/7.jpg
PCA_based Face Recognition System/TrainDatabase/8.jpg
PCA_based Face Recognition System/TrainDatabase/9.jpg

训练集合照片

10个人的训练集合照片差别是比较大的,表情、头部的位置都不相同。

测试集合照片 的差别也是比较大的,与训练集合相似度也不大,远远达不到利用像素对比实现图像识别的能力。

 

 

 主程序包含下面几个文件


PCA_based Face Recognition System/example.m

    用于设定训练集合目录、测试集合目录,链接其余函数。

 

PCA_based Face Recognition System/CreateDatabas.m

    用于将训练集合照片转为灰度照片,然后将照片转换为列向量,最后将所有的训练集合照片形成矩阵


PCA_based Face Recognition System/EigenfaceCore.m

   用于对训练集合矩阵标准化,然后求标准化矩阵的相关矩阵的特征根和特征向量。

根据特征值的贡献率,选择大于1的特征根作为主成份分量。 组合主成份分量对应的特征向量为特征向量矩阵。

标准化后的训练集合矩阵与特征向量矩阵相乘得到特征脸核函数。


PCA_based Face Recognition System/Recognition.m

    将原始的训练集合彩色照片与特征脸核函数相乘,映射训练集合照片到特征脸空间中。

将测试照片与特征脸核函数相乘,映射测试照片到特征脸空间中。

在特征脸空间求测试照片与每一个训练集合照片的方差,方差最小的训练集合照片编号,就是测试照片鉴别结果。

 

下面对代码进行注释

example.m

% A sample script, which shows the usage of functions, included in
% PCA-based face recognition system (Eigenface method)
%
% See also: CREATEDATABASE, EIGENFACECORE, RECOGNITION

% Original version by Amir Hossein Omidvarnia, October 2007
% Email: aomidvar@ece.ut.ac.ir

// 清理运行环境

 

clear all
clc
close all

// 定义训练集合、测试集合的位置以及测试照片的编号

% You can customize and fix initial directory paths 

TrainDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select training database path' );
TestDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select test database path');

 prompt = {'Enter test image name (a number between 1 to 10):'};

dlg_title = 'Input of PCA-Based Face Recognition System';
num_lines= 1;
def = {'1'};

TestImage = inputdlg(prompt,dlg_title,num_lines,def);
TestImage = strcat(TestDatabasePath,'\',char(TestImage),'.jpg');

// 读入测试照片
im = imread(TestImage);

// 将训练集合照片转换为灰度的训练集合矩阵.

T = CreateDatabase(TrainDatabasePath);

// 将灰度的训练集合矩阵转换为特征脸核函数
[m, A, Eigenfaces] = EigenfaceCore(T);

//将测试照片 训练集合 利用特征脸核函数进行鉴别
OutputName = Recognition(TestImage, m, A, Eigenfaces);

//根据鉴别结果从训练集合中选择原始照片

SelectedImage = strcat(TrainDatabasePath,'\',OutputName);
SelectedImage = imread(SelectedImage);

//输出鉴别结果
figure
imshow(im)
title('Test Image');
figure,imshow(SelectedImage);
title('Equivalent Image');

str = strcat('Matched image is : ',OutputName);
disp(str)

 

 

CreateDatabas.m

 // 定义函数,输入变量为训练集合路径

function T = CreateDatabase(TrainDatabasePath)
% Align a set of face images (the training set T1, T2, ... , TM )
%
% Description: This function reshapes all 2D images of the training database
% into 1D column vectors. Then, it puts these 1D column vectors in a row to
% construct 2D matrix 'T'.
%
%
% Argument: TrainDatabasePath - Path of the training database
%
% Returns: T - A 2D matrix, containing all 1D image vectors.
% Suppose all P images in the training database
% have the same size of MxN. So the length of 1D
% column vectors is MN and 'T' will be a MNxP 2D matrix.
%
% See also: STRCMP, STRCAT, RESHAPE

% Original version by Amir Hossein Omidvarnia, October 2007
% Email: aomidvar@ece.ut.ac.ir

%%%%%%%%%%%%%%%%%%%%%%%% File management

//得到训练集合的文件
TrainFiles = dir(TrainDatabasePath);
Train_Number = 0;

for i = 1:size(TrainFiles,1)
if not(strcmp(TrainFiles(i).name,'.')|strcmp(TrainFiles(i).name,'..')|strcmp(TrainFiles(i).name,'Thumbs.db'))
Train_Number = Train_Number + 1; % Number of all images in the training database
end
end

%%%%%%%%%%%%%%%%%%%%%%%% Construction of 2D matrix from 1D image vectors

// 将训练集合照片拼接为矩阵
T = [];
for i = 1 : Train_Number

% I have chosen the name of each image in databases as a corresponding
% number. However, it is not mandatory!

// 拼接训练集合照片 路径和文件名
str = int2str(i);
str = strcat('\',str,'.jpg');
% strg = strcat('\',str,'_g.jpg');
str = strcat(TrainDatabasePath,str);
% strg = strcat(TrainDatabasePath,strg);

//读取训练照片,并转为灰度照片
img = imread(str);
img = rgb2gray(img);
% imwrite(img,strg);
[irow icol] = size(img);

// 将照片转为列向量,按照先行再列的顺序转换为irow*icol行的列向量
temp = reshape(img',irow*icol,1); % Reshaping 2D images into 1D image vectors

//拼接列向量为矩阵
T = [T temp]; % 'T' grows after each turn
end

 

 

EigenfaceCore.m

// 定义函数,输入为的训练集合照片灰度矩阵

   输出m为训练集合照片灰度矩阵的行均值的列向量

   输出A为训练集合照片灰度矩阵的偏差矩阵

   输出Eigenfaces 为训练集合得到的特征脸核函数

function [m, A, Eigenfaces] = EigenfaceCore(T)
% Use Principle Component Analysis (PCA) to determine the most
% discriminating features between images of faces.
%
% Description: This function gets a 2D matrix, containing all training image vectors
% and returns 3 outputs which are extracted from training database.
%
% Argument: T - A 2D matrix, containing all 1D image vectors.
% Suppose all P images in the training database
% have the same size of MxN. So the length of 1D
% column vectors is M*N and 'T' will be a MNxP 2D matrix.
%
% Returns: m - (M*Nx1) Mean of the training database
% Eigenfaces - (M*Nx(P-1)) Eigen vectors of the covariance matrix of the training database
% A - (M*NxP) Matrix of centered image vectors
%
% See also: EIG

% Original version by Amir Hossein Omidvarnia, October 2007
% Email: aomidvar@ece.ut.ac.ir

%%%%%%%%%%%%%%%%%%%%%%%% Calculating the mean image

// 求训练集合灰度照片矩阵的行均值
m = mean(T,2); % Computing the average face image m = (1/P)*sum(Tj's) (j = 1 : P)
Train_Number = size(T,2);

%%%%%%%%%%%%%%%%%%%%%%%% Calculating the deviation of each image from mean image

// 利用行均值求的训练集合照片灰度矩阵的偏差值。得到偏差矩阵
A = [];
for i = 1 : Train_Number
temp = double(T(:,i)) - m; % Computing the difference image for each image in the training set Ai = Ti - m
A = [A temp]; % Merging all centered images
% normal1 = reshape(temp,180,200);
% imwrite(normal1',[num2str(i),'_normal.jpg']);
end

%%%%%%%%%%%%%%%%%%%%%%%% Snapshot method of Eigenface methos
% We know from linear algebra theory that for a PxQ matrix, the maximum
% number of non-zero eigenvalues that the matrix can have is min(P-1,Q-1).
% Since the number of training images (P) is usually less than the number
% of pixels (M*N), the most non-zero eigenvalues that can be found are equal
% to P-1. So we can calculate eigenvalues of A'*A (a PxP matrix) instead of
% A*A' (a M*NxM*N matrix). It is clear that the dimensions of A*A' is much
% larger that A'*A. So the dimensionality will decrease.

// 求出偏差矩阵的相关矩阵,以及相关矩阵的特征值D和特征向量V

L = A'*A; % L is the surrogate of covariance matrix C=A*A'.
[V D] = eig(L); % Diagonal elements of D are the eigenvalues for both L=A'*A and C=A*A'.
% diag(D)
% V
%%%%%%%%%%%%%%%%%%%%%%%% Sorting and eliminating eigenvalues
% All eigenvalues of matrix L are sorted and those who are less than a
% specified threshold, are eliminated. So the number of non-zero
% eigenvectors may be less than (P-1).

// 选择大于1的特征值作为主成份。提取对应的特征向量,拼接为特征向量矩阵。

L_eig_vec = [];
for i = 1 : size(V,2)
if( D(i,i)>1 )
L_eig_vec = [L_eig_vec V(:,i)];
end
end
% L_eig_vec

%%%%%%%%%%%%%%%%%%%%%%%% Calculating the eigenvectors of covariance matrix 'C'
% Eigenvectors of covariance matrix C (or so-called "Eigenfaces")
% can be recovered from L's eiegnvectors.

// 特征向量与训练集合照片偏差矩阵相乘,得到特征脸核函数
Eigenfaces = A * L_eig_vec; % A: centered image vectors
% for i = 1 : 19
% temp = Eigenfaces(:,i); % Computing the difference image for each image in the training set Ai = Ti - m
% normal1 = reshape(temp,180,200);
% imwrite(normal1',[num2str(i),'_Eigenfaces.jpg']);
% end

 

 

 

 Recognition.m

// 识别函数,输入为测试照片、均值向量、偏差矩阵和特征脸核函数

function OutputName = Recognition(TestImage, m, A, Eigenfaces)
% Recognizing step....
%
% Description: This function compares two faces by projecting the images into facespace and
% measuring the Euclidean distance between them.
%
% Argument: TestImage - Path of the input test image
%
% m - (M*Nx1) Mean of the training
% database, which is output of 'EigenfaceCore' function.
%
% Eigenfaces - (M*Nx(P-1)) Eigen vectors of the
% covariance matrix of the training
% database, which is output of 'EigenfaceCore' function.
%
% A - (M*NxP) Matrix of centered image
% vectors, which is output of 'EigenfaceCore' function.
%
% Returns: OutputName - Name of the recognized image in the training database.
%
% See also: RESHAPE, STRCAT

% Original version by Amir Hossein Omidvarnia, October 2007
% Email: aomidvar@ece.ut.ac.ir

%%%%%%%%%%%%%%%%%%%%%%%% Projecting centered image vectors into facespace
% All centered images are projected into facespace by multiplying in
% Eigenface basis's. Projected vector of each face will be its corresponding
% feature vector.

 

// 将训练集合照片映射到特征脸空间

ProjectedImages = [];
Train_Number = size(Eigenfaces,2);
for i = 1 : Train_Number
temp = Eigenfaces'*A(:,i); % Projection of centered images into facespace
i
temp
ProjectedImages = [ProjectedImages temp];
end
size(ProjectedImages)
% xx = 1:19;
figure
mesh(ProjectedImages)
xlabel('Number of Face');
ylabel('Number of Eigen');
zlabel('value of Eigen');
%%%%%%%%%%%%%%%%%%%%%%%% Extracting the PCA features from test image

// 映射测试照片到特征脸空间
InputImage = imread(TestImage);
temp = InputImage(:,:,1);

[irow icol] = size(temp);
InImage = reshape(temp',irow*icol,1);
Difference = double(InImage)-m; % Centered test image
ProjectedTestImage = Eigenfaces'*Difference; % Test image feature vector
size(ProjectedTestImage)
figure
plot(ProjectedTestImage)
xlabel('number of eigen')
ylabel('value of eigen')
%%%%%%%%%%%%%%%%%%%%%%%% Calculating Euclidean distances
% Euclidean distances between the projected test image and the projection
% of all centered training images are calculated. Test image is
% supposed to have minimum distance with its corresponding image in the
% training database.

// 求测试照片与训练集合照片的方差

Euc_dist = [];
figure
for i = 1 : Train_Number
q = ProjectedImages(:,i);
temp = ( norm( ProjectedTestImage - q ) )^2;
Euc_dist = [Euc_dist temp];
end
figure
plot(Euc_dist)
xlabel('number of face')
ylabel('value of variance')

// 方差最小的训练集合照片就是鉴别结果

[Euc_dist_min , Recognized_index] = min(Euc_dist);
OutputName = strcat(int2str(Recognized_index),'.jpg');