目录
一、理论基础
人脸识别技术是一种广泛应用于安防、金融、医疗等领域的技术,它可以识别出人脸图像中的人物身份信息。2D-LDA(Two-dimensional Linear Discriminant Analysis)是一种常用的特征提取方法,它可以提取不同维度的特征,从而提高识别率。本文将从数学公式和实现步骤两个方面,详细介绍基于2D-LDA特征提取的人脸识别算法及其识别率曲线。
1.1 LDA特征提取
在介绍2D-LDA特征提取之前,我们先来回顾一下LDA特征提取。LDA特征提取是一种常用的分类方法,它通过对数据进行降维,同时保留了数据的分类信息,从而提高了分类的准确率。
假设我们有一个由$n$个样本组成的数据集$X={x_1,x_2,...,x_n}$,每个样本有$d$维特征和一个类别标签$y_i$,我们的目标是将这个数据集降到$k$维,使得降维后的数据能够最大化不同类别之间的距离,同时最小化同一类别内部的距离。我们可以通过对两个矩阵$S_w$和$S_b$进行特征值分解,得到特征向量矩阵$W$,将每个样本$x_i$乘以变换矩阵$W$,得到降维后的样本$y_i=W^Tx_i$。LDA的数学公式如下:
计算每个类别的均值:
$$\overline{x}i=\frac{1}{n_i}\sum{j=1}^{n_i}x_{ij},\quad i=1,2,...,c$$
其中,$c$为类别数,$n_i$为第$i$个类别的样本数。
计算总体均值:
$$\overline{x}=\frac{1}{n}\sum_{i=1}^c\sum_{j=1}^{n_i}x_{ij}$$
其中,$n$为总样本数。
计算类内散度矩阵$S_w$:
$$S_w=\sum_{i=1}^c\sum_{j=1}^{n_i}(x_{ij}-\overline{x}i)(x{ij}-\overline{x}_i)^T$$
计算类间散度矩阵$S_b$:
$$S_b=\sum_{i=1}^c n_i(\overline{x}_i-\overline{x})(\overline{x}_i-\overline{x})^T$$
对矩阵$S_w^{-1}S_b$进行特征值分解:
$$S_w^{-1}S_b=V\Lambda V^T$$
其中,$V$为特征向量矩阵,$\Lambda$为特征值对角矩阵。
取最大的$k$个特征向量:
$$W=[v_1,v_2,...,v_k]$$
对每个样本进行变换:
$$y_i=W^Tx_i$$
其中,$k$为降维后的维数,$y_i$为降维后的样本向量。
1.2 2D-LDA特征提取
2D-LDA特征提取是LDA的一种扩展,它可以提取不同维度的特征,从而提高识别率。与LDA不同的是,2D-LDA对两个方向的散度矩阵进行特征值分解,得到不同的特征向量矩阵$W_1$和$W_2$,分别对应不同的特征维度,具体数学公式如下:
计算每个类别的均值:
$$\overline{x}i=\frac{1}{n_i}\sum{j=1}^{n_i}x_{ij},\quad i=1,2,...,c$$
其中,$c$为类别数,$n_i$为第$i$个类别的样本数。
计算总体均值:
$$\overline{x}=\frac{1}{n}\sum_{i=1}^c\sum_{j=1}^{n_i}x_{ij}$$
其中,$n$为总样本数。
计算类内散度矩阵$S_w$:
$$S_w=\sum_{i=1}^c\sum_{j=1}^{n_i}(x_{ij}-\overline{x}i)(x{ij}-\overline{x}_i)^T$$
计算类间散度矩阵$S_b$:
$$S_b=\sum_{i=1}^c n_i(\overline{x}_i-\overline{x})(\overline{x}_i-\overline{x})^T$$
对矩阵$S_w$和$S_b$分别进行特征值分解:
$$S_w=V_1\Lambda_1 V_1^T,\quad S_b=V_2\Lambda_2 V_2^T$$
其中,$V_1$和$V_2$分别为特征向量矩阵,$\Lambda_1$和$\Lambda_2$分别为特征值对角矩阵。
取最大的$k_1$个特征向量:
$$W_1=[v_{11},v_{12},...,v_{1k_1}]$$
取最大的$k_2$个特征向量:
$$W_2=[v_{21},v_{22},...,v_{2k_2}]$$
其中,$k_1$和$k_2$分别为降维后的维数,$W_1$和$W_2$分别为特征向量矩阵。
对每个样本进行变换:
$$y_{i1}=W_1^Tx_i,\quad y_{i2}=W_2^Tx_i$$
其中,$y_{i1}$和$y_{i2}$分别为降维后的样本向量。
1.3实现步骤
基于以上数学公式,我们可以实现基于2D-LDA的人脸识别算法。具体步骤如下:
准备数据集:收集并整理人脸图像数据集,将每个人的图像按照一定比例分成训练集和测试集。
数据预处理:对每个图像进行预处理,包括人脸检测、人脸对齐、图像增强等操作,以提高识别率。
特征提取:对每个训练样本进行特征提取,得到降维后的样本向量$y_{i1}$和$y_{i2}$。
训练模型:将降维后的样本向量输入到分类模型中进行训练,得到分类器。
测试模型:对测试集中的每个样本进行预测,计算预测准确率,并绘制识别率曲线。
调整参数:根据识别率曲线,调整模型参数,以提高识别率。
识别率曲线
识别率曲线是评估人脸识别算法性能的一种常用方法,它可以直观地反映算法的识别效果。在基于2D-LDA的人脸识别算法中,我们可以通过绘制不同维数下的识别率曲线,来评估算法的性能。
具体绘制识别率曲线的步骤如下:
将数据集分成训练集和测试集,以一定比例划分,如70%的数据用于训练,30%的数据用于测试。
对训练集中的每个样本进行特征提取,得到降维后的样本向量$y_{i1}$和$y_{i2}$。
将降维后的样本向量输入到分类模型中进行训练,得到分类器。
对测试集中的每个样本进行预测,计算预测准确率。对于每个不同的维数$k_1$和$k_2$,重复以上步骤,得到对应的识别率。
二、核心程序
...........................................................................
height = 112;
width = 92;
%%%%%%%%%%%%%%训练样本Xtrain%%%%%%%%%%
for i=1:nclass
for j = 1:neachtrain
Xtrain(:,(i-1)*neachtrain+j) = facedatabase(:,(i-1)*(nsmpaleeachclass)+j*2-1);
end
end
%%%%%%%%%%%%%%测试样本Xtest,一列表示一幅图像%%%%%%%%%%
for i=1:nclass
for j = 1:neachtest
Xtest(:,(i-1)*neachtest+j) = facedatabase(:,(i-1)*(nsmpaleeachclass)+j*2);
end
end
for i=1:neachtrain*nclass
trainSample{i}=reshape(Xtrain(:,i), height, width);
end
%总训练样本数neachtrain*nclass
for i=1:neachtest*nclass
testSample{i}=reshape(Xtest(:,i), height, width);
end
%总测试样本数neachtrain*nclass
[vec, val] = tdfda(trainSample, nclass);%调用tdfda,输入训练样本和类别数,返回降序排列的 特征值和特征向量
for d=2:2:20
for i=1:neachtrain*nclass
newTrainSample{i} = trainSample{i}*vec(:,1:d);
newTestSample{i} = testSample{i}*vec(:,1:d);
newXtrain(i,:) = reshape(newTrainSample{i}, 1, height*d);%每幅图像展开成一行 新的特征表示
newXtest(i,:) = reshape(newTestSample{i}, 1, height*d);
end
%re_im{d/5} = uint8(newTrainSample{1}*vec(:,1:d)');
tic%启动计时器
classification=classif(newXtrain', newXtest');%调用classification,输入训练矩阵和测试矩阵,返回类别
size(classification);
suc(d/2) = success(classification, neachtrain, neachtest);%调用success,返回识别率suc(d/2)
t(d/2)=toc;%关闭计时器
clear newTrainSample newTestSample newXtrain newXtest;
end
%%%%%%%%%%%%%%%%%%%%%%显示%%%%%%%%%%%%%%%%%%%%%
disp('对应不同特征数d的识别率:');
suc
disp('对应不同特征数d的识别耗时:');
t
%%%%%%%%%%%%%%%%%%%%画图%%%%%%%%%%%%%%%%%%%%%%%%
box
axis([2 20 0.65 1.00]);
set(gca,'Xtick',[2:2:20],'ytick',[0.7:0.05:1.00]);
ylabel('识别率suc');
xlabel('特征数d');
hold on;
plot(2:2:20,suc,'-^')
up2148