2017年认证杯SPSSPRO杯数学建模
跨年龄人脸识别模型的建立与分析
B题 岁月的印记
原题再现:
对同一个人来说,如果没有过改变面容的疾病、面部外伤或外科手术等经历,年轻和年老时的面容总有很大的相似性。人们在生活中也往往能够分辨出来两张不同年龄段的照片是不是同一个人。当然,年龄段相差越大,识别起来也就越困难。
第一阶段问题: 请你建立合理的数学模型,当我们给出两张不同年龄段的面部照片时,可以通过算法来自动识别是不是同一个人。为简单起见,我们可以假设两张照片都是标准位置和标准光线下拍摄的,例如都是一寸证件照。
整体求解过程概述(摘要)
对于同一个人不同年龄的两张照片,如何通过算法来自动识别这两张照片是否来自同一人,这个问题可以看做是人脸识别技术的一个子问题,侧重点在于所设计的算法要能够针对不同年龄段的照片给出准确的判断。为了提高算法的识别率,需要尽可能多地提取能够刻画人脸在不同年龄段状态下的特征。为了准确分析、全面考虑问题,我们从不同的角度出发,分别建立模型、通过实验进行模型有效性及敏感性分析等。本文主要从主成分分析法、人脸特征距离和特征角相似性度量以及使用BP神经网络提取特征向量、训练相似性判断模型等角度对问题进行解决。
本文首先在传统的基于主成分分析的人脸识别算法的基础上提出一种改进算法(ModPCA_FR),在特征提取之前不需要将人脸图像矩阵展开为一维的向量,减小了后续算法的计算复杂度,同时对每一类训练样本求类内平均脸,计算图像协方差矩阵,并根据图像协方差矩阵求解一组最优特征向量来用于人脸的特征提取。通过在 ORL 人脸数据库中进行 matlab 编程实验验证了该方法在年龄跨度 2 年内准确识别的有效性。其次,由于 ModPCA_FR 模型在人脸识别中对于年龄跨度有一定的敏感性,本文建立了基于提取特征距离及特征角的不同年龄段人脸匹配模型。该模型可以对任意两张跨年龄段的图片进行匹配,不会受到年龄差太大等因素的影响,可以以较高的准确率匹配照片。另外,该模型对人类年龄进行了分类,并最终通过大量实验证明算法不仅可以对同一年龄段人的照片准确识别,而且对于跨年龄段的同一个人的照片依然有较好的匹配效果。同时对非同一人的跨年龄照片也能够准确识别。
最后,本文提出一种基于 BP 神经网络的人脸判别模型。该模型是基于 PCA 降维模型的推广模型,即在对数据进行降维,提取人脸面部主要特征(奇异特征值)构成照片的特征向量。接着,将不同照片(包含同人不同年龄和不同人不同年龄)的特征向量进行随机组合,形成神经网络输入集,并且控制同人和不同人的比率为 50%。之后,将输入集分为训练集和测试集,用于训练和测试神经网络。最后,给出输入集的识别率,其中总体识别率为 80.81%。
问题分析:
对于同一个人不同年龄的两张照片,在本人的面部没有遭受过非自然成长损伤的情况下,人们在生活中可以通过观察判断两张照片是否来自同一个人。如果这两张照所拍摄的时间相差越长,则辨别起来就越难。题目要求设计算法来自动识别不同年龄段的两张照片是不是来自同一个人。这个问题可以看做是人脸识别技术的一个子问题,这个问题的侧重点在于所设计的算法要能够准确判断不同年龄段的照片是否来自同一个人。当然,为了突出跨年龄段识别这个重点,我们可以简化问题,如:暂不考虑两张图片的拍摄角度、曝光量等可以影响照片分析的因素。为了提高算法识别率,我们需要尽可能多地提取能够刻画人脸在不同年龄段状态下的特征。为了准确分析、全面考虑问题,我们将从不同的角度出发,分别建立模型、进行实验以及模型有效性分析等。主要将从主成分分析法、人脸特征距离和特征角方面以及使用BP神经网络提取特征向量、训练相似性判断模型等角度进行问题的解决。
模型假设:
1. 假设两张照片都是标准位置和标准光线下拍摄的;
2. 假设人脸没有经过任何外在装饰,且在自然表情状态下拍摄;
3. 假设待识别的人脸是面部对称的;
4. 假设年龄对所有人的影响是一致的。
论文缩略图:
全部论文请见下方“ 只会建模 QQ名片” 点击QQ名片即可
部分程序代码:(代码和文档not free)
%读入人脸图片,并将其转换成为灰度矩阵,然后将灰度矩阵进行切割,再用SVD分解,
并提取图片特征
%返回参数
%feature为指向装载后的数据文件的变量
%num的值为特征值向量的第几维
%函数声明
function [feature] = allFeature(num)
%用户输入特征维数数目
panDuan = 1;
while panDuan
featureNumber = input('请输入特征维数(仅限于8, 16,24, 32,48,64,80):');
%如果输入的是8.16.24.32.48.64.80,则继续执行代码
if(featureNumber == 8||featureNumber == 16 || featureNumber == 24|| featureNumber == 32 || featureNumber == 48 || featureNumber == 64 || featureNumber == 80 )
panDuan = 0;
disp('开始装载图像文件,请等待.......')
%如果输入的是其它数字,提示输入有误,请用户重新输入
else
fprintf('你输入的不是这5个数中的任何一个,请重新输入!\n\n')
end
end
%得出图片的路径,并自动读入每张图片
dir = ['\1.jpg '
'\2.jpg '
'\3.jpg '
'\4.jpg '
'\5.jpg '
'\6.jpg '
'\7.jpg '
'\8.jpg '
'\9.jpg '
'\10.jpg'];
for x=1:10,
%将数字转换成字符,便于把两个字符连接,组成图片的完整路径
a = int2str(x);
b = ['s'];
d = [b a];
for i=1:10,
%得到每张图片的文件名
e = [d dir(i,1:7)];
% 将图片转化成为灰度矩阵
M = double(imread(e));
%如果用户输入的是8,则执行下段代码,把数据处理得到8维的特征向量
if (featureNumber == 8)
for j=1:4,
for k=1:2,
%将图片的灰度矩阵划分成8块小矩阵
temp=M((j-1)*28+1:j*28,(k-1)*46+1:k*46);
%对每个小矩阵进行SVD变换
[u,temp1,v]=svd(temp);
%提取一个的SVD系数作为特征值
temp2=temp1(num,num);
%得到所有图片的特征矩阵
feature((x-1)*10+i,(j-1)*2+k)=temp2;
end
end
end
%如果用户输入的是16,则执行下段代码,把数据处理得到16维的特征向量
end
end
%输出提示信息,说明图片处理完毕
fprintf('图片装载完毕,请继续下面的操作\n\n');
function [c] = Distance( D1,D2 )
%DRULE D1,D2位两个D数表示,该函数求D1与D2之间的距离
[m1,n1]=size(D1);
[m2,n2]=size(D2);
% D1(:,2)=D1(:,2)*10000;
% D2(:,2)=D2(:,2)*10000;
C=0;
if (sum(D1(:,2))+1)-1==1 && (sum(D1(:,2))+1)-1==1
for i=1:m1
for j=1:m2
C=C+(D1(i,2)+D2(j,2))/2;
end
end
end
ccc=0;
if (sum(D1(:,2))+1)-1<1 && (sum(D1(:,2))+1)-1==1
for i=1:m1
for j=1:m2
C=C+(D1(i,2)+D2(j,2))/2;
end
end
vc1=1-sum(D1(:,2));
for j=1:m2
ccc=ccc+(vc1+D2(j,2))/2;
end
C=C+ccc;
ccc=0;
end
if (sum(D1(:,2))+1)-1==1 && (sum(D1(:,2))+1)-1<1
disp('ccc');
for i=1:m1
for j=1:m2
C=C+(D1(i,2)+D2(j,2))/2;
end
end
vc2=1-sum(D2(:,2));
for j=1:m1
ccc=ccc+(D1(j,2)+vc2)/2;
end
C=C+ccc;
end
ccc1=0;
ccc2=0;
if (sum(D1(:,2))+1)-1<1 && (sum(D1(:,2))+1)-1<1
for i=1:m1
for j=1:m2
C=C+(D1(i,2)+D2(j,2))/2;
end
end
vc1=1-sum(D1(:,2));
vc2=1-sum(D2(:,2));
for j=1:m2
ccc1=ccc1+(vc1+D2(j,2))/2;
end
for j=1:m1
ccc2=ccc2+(D1(j,2)+vc2)/2;
end
C=C+ccc1+ccc2+(vc1+vc2)/2;
end
hang=1;
for i=1:m1
for j=1:m2
D(hang,1)=(D1(i,1)+D2(j,1))/2;
D(hang,2)=((D1(i,2)+D2(j,2))/2)/C;
hang=hang+1;
end
end
[Cf,IA,IC] = unique(D(:,1),'sorted');
c(:,1) = Cf;
for k=1:length(Cf)
d = find(D(:,1)==Cf(k));
c(k,2) = sum(D(d,2));
end
End