一、简介
本文所用的是ORL人脸库,由英国剑桥实验室拍摄,共有40人,每人不同角度不同表情拍摄了10张,所以共有400个样本数据,图片尺寸为11292,格式为pgm。本文将每人的前5张作为训练集,后5张作为测试集。ORL人脸库可在该网址下载https://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
1 什么是人脸识别?
人脸识别技术,就是以计算机为辅助手段,从静态或动态图像中识别人脸。
本问题中的人脸识别,是给定一幅人物图,利用人脸数据库 来与之进行匹配,判断其是否属于此数据库。若是,给出她所属的类别。
2 为什么选择人脸作为识别特征来识别?
因为人脸和指纹一样,具有唯一性,可以用来鉴别一个人的身份。
也就是说,我们想要识别一个东西,要选它主要的特征,辨识度区分度高的特征,这样识别结果才可靠。 就像我们要识别一个人,为什么不去识别他的身高,体重,肤色,眼睛大小啥的?因为这些没有独特性,作为数据来说,太普通了,两个人身高体重肤色相同的概率还是很大的,所以不能作为唯一辨识特征。而选择DNA、指纹、虹膜等属性来作为识别一个人特征,就是因为这些属性具有唯一性,这世界上,不会有人和你在这些特征上重样。
3 人脸识别是怎么进行的?
(1)找感兴趣区域----从复杂场景中检测并分离出人脸所在的区域;
(2)抓特征—抽取人脸识别特征;
(3)匹配吧—进行匹配和识别;
4 为了实现人脸识别,你要做什么?
(1)人脸数据库ORL
(2)数据库中的人脸图片一部分用来做训练数据,建立模型。
(3)另一部分可以用来做测试数据,检验识别率。
5 PCA主成分分析来降维
(1)为什么要降维?
因为每幅人脸图像包含11292=10304个像素点,每一行代表一个样本,那维度就是10304维。
如此巨大的维数使得数据处理工作很是艰难,也打消了我们直接利用像素点作为特征值来识别的念头。
(2)PCA是什么?它怎么来实现降维的?
PCA是主成分分析(principal component analysis).利用PCA降维去除像素之间的相关性,取出主成分,同时抛弃那些不能为我们提供重要特征信息的分量。
PCA 通过对样本数据中各成分分量(10304维)进行排序,可选出主要成分,构成主成分分量V(n*k)矩阵(k维)且输出降维后的k维矩阵pcaA。
b1) 其中主成分矩阵V 可在 test.m 和 classify.m中直接带入公式求得降维后的矩阵。
b11) test.m中, TestFace = (TestFace-repmat(meanVec, m, 1))*V; %多个样本数据 经过pca变换降维
b12) classify.m中,xNewFace=(xNewFace-meanVec)*V; %单个样本数据 经过PCA变换降维
b2) 其中输出的k维矩阵pcaA将代替 原样本数据 参与后续数据处理,即pcaA成为样本。
3 数据规格化scaling
(1)数据规格化是什么?
数据规格化又称数据尺度归一化,是指将某一属性的取值范围 投射到一个特定范围之内,例如常用的[0,1]或[-1,+1]归一化。
b) 数据规格化的作用?
b1) 防止那些处于相对较大的数值范围的特征 压倒那些数值范围小的 特征。例如:几个人具有变化范围大的身高(150cm-180cm)以及 变化范围小的体重(50kg-60kg), 数据规格化后,两个属性的变化差异就缩小了,很好的保护了 变化范围小的 属性依旧能对目标识别起到重要作用。
b2) 避免一些数据溢出问题,统一放缩到同一范围,例如,把数据都限定在[-1,+1]区间,让那些大个子也不得不低头。
6 SVM分类识别
a)SVM是什么?
SVM支持向量机(support vector machine)。SVM是一种分类的方法,通过训练数据来建立分类模型,将分类模型用于对测试数据的分类。就相当于是叠了一个黑盒子,然后你往里扔小球(测试数据),他就能把小球分好类。当然前提是,你得用一堆小球(训练数据)去建立这样一个黑盒。
a1) SVMTrain —通过训练数据来建立分类模型SVMStruct
a2) SVMClassify —通过模型来对测试数据进行分类识别
b) SVM的优点?
传统模式识别技术只考虑分类器对训练样本的拟合情况,以最小化训练集上的分类错误为目标。然而在缺乏代表性的小训练集情况下,一味降低训练集上的错误,容易导致过度拟合。 这就叫只注重已有的(训练数据),不懂得审时度势,要放眼未来(测试数据)啊大兄弟!
这时候,SVM出现了,她懂得权衡利弊,而不是一味追求完美的训练数据拟合,她呢兼顾了训练误差与测试误差,以求得全局胜利,真是有智慧的女神! 让传统识别技术的屌丝哥哥们望尘莫及啊!
c) SVM的重点?
SVM的重点,在于分类模型的选择和模型参数的选择。
c1) 分类模型:通过控制分类模型的复杂性可以防止过度拟合,因此SVM更偏爱解释数据的简单模型—二维空间中的直线,三维空间中的平面,以及更高维空间中的超平面。
c2) 参数选择:参数选择的依据是–>寻找最优分类超平面,即寻找能成功分开两类样本 且 具有最大分类间隔的最优分类超平面。
d) SVM的技术热点有什么?
核函数:低维无法将两类样本分开时,可采用非线性映射到高维,利用超平面分开。从低维到高维的映射这就用到了核函数,而且核函数很神奇的无需知道具体映射关系就能给你实现某一非线性分类变换后的线性分类,且计算复杂度相较于低维并未增加。这,简直就是个天才函数!核函数。常用核函数有:线性核函数、多项式核函数、径向基核函数、Sigmoid核函数。(知道函数表达式,找出参数,就可带进去直接用了)
SVM推广到多类:因为SVM是一个二分器,她的基本思想是分开两类样本,即只能用于两类样本的分类。若想识别多类,需用到一些策略。常用的策略有:一对多的最大响应策略、 一对一的投票策略、一对一的淘汰策略。
7 人脸识别算法步骤概述:
(1)读取训练数据集;
(2)主成分分析法降维并去除数据之间的相关性;
(3)数据规格化(去除数据单位因素对分类造成的影响,这个对此实验造成的影响不大);
(4)SVM训练(选取径向基和函数);
(5)读取测试数据、降维、规格化;
(6)用步骤4产生的分类函数进行分类(多分类问题,采用一对一投票策略,归位得票最多的一类);
(7)计算正确率。
二、源代码
% FR_GUI.m
addpath(genpath('./'))
global h_axes1;
global h_axes2;
h_f = figure('name', '基于PCA和SVM的人脸识别系统');
h_textC = uicontrol(h_f, 'style', 'text', 'unit', 'normalized', 'string', 'C=', 'position',...
[0.05 0.7 0.1 0.06]);
h_editC = uicontrol(h_f, 'style', 'edit', 'unit', 'normalized', 'position', [0.05 0.6 0.1 0.06],...
'callback', 'C = str2num(get(h_editC, ''string''))');
h_textGamma = uicontrol(h_f, 'style', 'text', 'unit', 'normalized', 'string', 'gamma=', 'position',...
[0.05 0.5 0.1 0.06]);
h_editGamma = uicontrol(h_f, 'style', 'edit', 'unit', 'normalized', 'position', [0.05 0.4 0.1 0.06],...
'callback', 'gamma = str2num(get(h_editGamma, ''string''))');
% 取得参数 C 和 gamma 的当前值,即最近一次训练所使用的值
t = dir('Mat/params.mat');
if length(t) == 0
% 没有找到参数文件
C = Inf;
gamma = 1
else
load Mat/params.mat;
end
function [imgRow,imgCol,FaceContainer,faceLabel]=ReadFaces(nFacesPerPerson, nPerson, bTest)
% 读入ORL人脸库的指定数目的人脸前前五张(训练)
%
% 输入:nFacesPerPerson --- 每个人需要读入的样本数,默认值为 5
% nPerson --- 需要读入的人数,默认为全部 40 个人
% bTest --- bool型的参数。默认为0,表示读入训练样本(前5张);如果为1,表示读入测试样本(后5张)
%
% 输出:FaceContainer --- 向量化人脸容器,nPerson * 10304 的 2 维矩阵,每行对应一个人脸向量
if nargin==0 %default value
nFacesPerPerson=5;%前5张用于训练
nPerson=40;%要读入的人数(每人共10张,前5张用于训练)
bTest = 0;
elseif nargin < 3
bTest = 0;
end
img=imread('Data/ORL/S1/1.pgm');%为计算尺寸先读入一张
[imgRow,imgCol]=size(img);
FaceContainer = zeros(nFacesPerPerson*nPerson, imgRow*imgCol);
faceLabel = zeros(nFacesPerPerson*nPerson, 1);
% 读入训练数据
for i=1:nPerson
i1=mod(i,10); % 个位
i0=char(i/10);
strPath='Data/ORL/S';
if( i0~=0 )
strPath=strcat(strPath,'0'+i0);
end
strPath=strcat(strPath,'0'+i1);
strPath=strcat(strPath,'/');
tempStrPath=strPath;
for j=1:nFacesPerPerson
strPath=tempStrPath;
if bTest == 0 % 读入训练数据
strPath = strcat(strPath, '0'+j);
else
strPath = strcat(strPath, num2str(5+j));
end
FaceContainer((i-1)*nFacesPerPerson+j, :) = img(:)';
faceLabel((i-1)*nFacesPerPerson+j) = i;
end % j
end % i
三、运行结果
四、备注
版本:2014a