使用主成分分析(PCA)进行人脸识别
主成分分析(PCA)是一种无监督的非参数统计技术,主要用于机器学习的降维。PCA是一种通过将大数据集转化为小数据集来降低维度的方法,但要确保小数据集比大数据集包含更多信息。
通过减少数据集,我们也在减少准确性。然而,PCA的工作原则是用小的准确性换取简单性。这是因为较小的数据集更容易探索和可视化,从而使机器学习算法的数据分析更加容易和快速。
特征向量和特征值是线性代数的概念,用于计算协方差矩阵以确定数据的主成分。人脸识别是利用一个人的脸来识别他的过程。
Matlab有许多内置函数可以帮助计算主成分。在这篇文章中,我们将看到如何使用它来识别人脸。
使用PCA降低维度
降维涉及到在PCA空间内将大尺寸图像降为小尺寸的PCA表示。PCA空间是缩小后的图像的维度空间。
在空间域(标准尺寸),图像很大,也就是200 x 180 像素。当投射到PCA工作空间中的PCA时,这被减少为一维,即1 x 50 像素。
人脸图像数据库
在这个练习中,我们使用face94 数据库进行识别。该数据库有153个人的脸。图像的分辨率为180 x 200 像素。它有一些目录,如女性文件夹(20),男性文件夹(113)和男性工作人员(20)。
培训和测试的数据库准备
对于训练,总共选择了30个人,每个人考虑10张图像。因此,共取300张图像用于训练。首先,大小为MxN 的图像被重新塑造成大小为1xMN 的一维矢量。数据库中的图像的大小为180 x 200 像素。
这将产生一个巨大的一维矢量,大小为1 x 36000 像素,这在Matlab中计算协方差矩阵时产生了内存分配问题。因此,每张图片的大小将被减少一半,即90 x 100 像素。
为了测试,我们从剩余的个体中抽取10张图像。由于我们有30个剩余的个体,我们将有300张图像用于测试。然后我们创建一个文件夹,其中包含将用于训练的图像和将用于测试的图像。
Matlab程序
我们需要创建两个文件夹用于训练(trainDB)和测试(testDB)。trainDB中的所有图像应被命名为1.jpg,2.jpg,3.jpg...800.jpg 。使用IrfanView、format factory或其他任何软件来重命名图像。不需要重新命名那些用于测试的图像。
注意,Matlab用于训练和测试的脚本文件应该保存在trainDB文件夹中,并将trainDB的路径设置为Matlab运行程序的当前目录。
用于训练的Matlab程序
我们首先输入训练用图像的数量,即300张,并输入要保留的主导特征值,即50个。要保留的主要特征值是通过PCA空间后图像的新维度。
n = input('enter the no. of images for training');
L = input('enter the number of dominant eigen values to keep');
然后我们指定维度。正如我们前面所说,我们将把维度减少到一半,即90 x 100 ,然后初始化这个数据矩阵,它将是图像维度和训练图像数量的乘积,即300 x 900 。
这个过程如下所示。
M = 100; N = 90; % Required image dimensions
X = zeros(n, (m*n)); % Initialization of data matrix
T = zeros(n,L); %initializing transformed data set(T) in pca space(300*50)
然后,我们使用循环来读取训练文件夹中的所有图像,并将其转换为灰度图像,因为这些图像是彩色的。调整图像的大小,然后将它们重塑为一个一维矢量。
这是由一个for循环完成的,如图所示。
for count = 1:n
I = imread(sprintf('%d.jpg', count)); %Reading images
if size(I, 3)> 1 %This loop checks for only the colored images and convert them to gray scale
I = rgb2gray(I);
end
I = imresize(I,[1,M*N]); %reshaping images to 1-D vectors.
end
然后我们复制数据库以便进一步使用。
Xb = X; %Copy database for further use
然后,我们找到所有图像的平均值,并使用for循环从每10张图像中减去平均值。做这个减法是为了将原始图像从旧的x,y 坐标系统转移到新的u,v 轴系统。
u,v 系统是一个类似于 系统的系统。区别在于命名的变化。在这种情况下,U是X轴,V是Y轴。x,y
m = mean(X); % mean of all images
for i = 1:n
X(i,:) = X(i,:)-m; %Subtracting mean from each 1-D image
end
然后我们找到协方差矩阵。矩阵是用来描述不同维度之间的关系的。以一种更容易理解的方式,协方差矩阵被用来定义整个维度中的关系,作为每两个ranuik ;dom变量之间的关系。
Q = (X'*X)/(n-1); %Finding covariance matrix
然后我们使用eig 命令找到协方差矩阵(Q)的特征值和特征向量。
[Evecam, Evalm] = eig(Q); %Getting eigen values and eigen vectors of COV matrix[Q];
特征向量将存储在evacam ,而特征值则存储在evalm 。然后我们使用diag 函数提取特征值,所有这些值存储在eval
Eval = diag(Evalm); %Extracting all eigen values
然后对提取的特征值进行排序,得到最大的eval 值。排序后的eval 值存储在evalSorted ,相应的索引存储在index 。
这是通过以下方式完成的。
[Evalsorted, Index] = sort(Eval, 'descend'); %sorting Eigen values
然后我们对特征向量进行重新洗牌evacam 。这是为了将特征向量变为列向量,并按降序排列。在重新洗牌后,我们计算特征向量,以获得一个缩小的特征向量。这意味着在排序的特征向量中,我们考虑前L 个向量。如下面的代码所示,L 是50。
Evecsorted = Evecam(:, Index);
Ppca = Evecsorted(:, 1:L); %Reduced transformation matrix [Ppca]
然后我们使用for循环将每张图像投射到PCA空间。每幅图像从空间域和平均值中减去,然后乘以变换矩阵(ppca),并存储回矩阵T,这就是变换后的还原矩阵。这意味着每个图像都被投射到PCA空间,并被缩小到大小1 x L ,这就是1 x 50 。因此,巨大的1 x 9000 被缩小为1 x 50 。
代码如图所示。
for i = 1:n
T(i,:) = (Xb(i,:)-m)*Ppca; %projecting each image to pca space
end
当我们运行整个代码时,在命令窗口中,有一条命令要求用户输入用于训练的图像数量(300),然后输入主导特征值(50)。在输入所有这些值后,训练开始了。这个训练可以在Matlab窗口的左下角看到,如图所示,它被表示为繁忙。

我们将从训练中选择一些变量,并将它们储存起来,以便在测试中使用。这将有助于避免一次又一次地重新运行训练程序。具体做法如下。
- 在工作区,选择所有的变量,然后取消选择变量
m,M,n,N和ppca。 - 删除所有其他变量,然后点击保存工作区,将这些数据保存在trainDB文件夹中,成为
pcadb。
Matlab的测试代码
在测试之前,我们必须加载我们从训练中保存的变量。
%first load required variables in workspace for testing
clc;
load pcadb; %loading pcadb.mat file
然后我们从数据库中选择我们的测试图像,并使用imread 函数读取它。
[filename, pathname] = uigetfile('*.*', 'Select the Input image');
filewithpath = strcat(pathname, filename);
img = imread(filewithpath);
然后我们对图像进行复制,将其转换为灰度,调整图像的大小和形状。
imgo = img;
img = rgb2gray(img);
img = imresize(img,[1,M*N]);
然后我们将查询图像(输入图像)投影到PCA空间。这意味着我们从img ,减去平均图像m ,然后将这个结果与变换矩阵ppca 相乘,imgpca 就是PCA投影的图像。
imgpca = (double(img)-m)*Ppca; %projecting query image to PCA space
然后我们初始化差异数组,并使用for 循环来寻找距离差异。
distarray = zeros(n,1); %Initialize difference array
for i = 1:n
distarray(i) = sum(abs(T(i,:)-imgpca)); %Finding L1 distance
end
从上面找到的距离,我们计算出最小距离。最小距离意味着最大的匹配。相应的索引被存储在indx ,产生的图像被存储在result 。然后我们在当前目录中搜索,找到同名的图像。
[result, indx] = min(distarray); %Getting best match
resulting = imread(sprintf('%d.jpg', indx)); %Getting best matched image
这个result ,就是输出图像。然后我们绘制图像。
%plotting images
subplot(121)
imshow(imgo);
title('Query Face');
subplot(122)
imshow(resultimg);
title('Recognized Face');
当我们运行这个程序时,我们被要求从数据库中选择我们的图像。我们应该从testDB中选择任何图像。选择图像后,它被识别出来,如图所示。

结论
Matlab提供了一个合适的工具箱以方便识别不同的人脸。这可以通过使用各种机器学习算法来实现。
除此之外,Matlab还有许多内置的功能,使所有的活动(训练和测试过程)容易进行。