您的位置:首页 > 编程语言 > MATLAB

基于PCA的人脸识别_Matlab实现(个人研读之后的一些总结)

2016-06-05 20:29 906 查看
以下是我在查阅相关文献之后的一些个人的总结,望大神们指正。

基于PCA的人脸识别

PCA简介

这是百度百科的解析:

“对于一个训练集,100个对象模板,特征是10维,那么它可以建立一个100*10的矩阵,作为样本。求这个样本的协方差矩阵,得到一个10*10的协方差矩阵,然后求出这个协方差矩阵的特征值和特征向量,应该有10个特征值和特征向量,我们根据特征值的大小,取前四个特征值所对应的特征向量,构成一个10*4的矩阵,这个矩阵就是我们要求的特征矩阵,100*10的样本矩阵乘以这个10*4的特征矩阵,就得到了一个100*4的新的降维之后的样本矩阵,每个特征的维数下降了。

人脸识别实现的主要步骤

人脸识别主要分为了两个主要的部分,一个是人脸训练,另一个重要的部分是人脸测试。(为了提高识别的准确率,可以首先对图片进行一些预处理,比如是图片的平滑,锐化,小波过滤等等,降低背景,还有图片角度对识别结果的影响)

人脸训练部分:

读取训练数据,将图片存到矩阵中。

利用PCA对图片矩阵进行降维和特征提取(对于特征提取和降维,还可以使用SVD奇异值分解的方法,但是在本文中主要使用的是PCA方法)

训练特征数据规范化

SVM样本训练

对于人脸识别的部分(其实和人脸训练部分类似):

1.读取测试数据。

测试数据降维

测试特征数据规范化

样本分类

附上Matlab GUI代码:



GUI界面包括了三个按钮(faceGui.m)

测试准确率,就是人脸训练,将样本集中的前5张作为训练的样本,将样本中后5张作为测试样本,测试人脸识别的准确率。

选择图片,选择图片是选择一张图片作为人脸识别使用

图像匹配,就是人脸识别

global h_axes1;
global h_axes2;
global edit2;
h_f=figure('name','人脸识别系统','position',[300,200,600,400]);
%clf reset;%clf 清除当前的图像的所有自图像,Reset重新设置图像的目标属性为默认值
set(h_f,'defaultuicontrolfontsize',12);
set(h_f,'defaultuicontrolfontname','宋体');

h_axes1=axes('parent',h_f,'position',[0.2,0.28,0.25,0.56],'Unit','normalized','visible','on');
h_axes2=axes('parent',h_f,'position',[0.55,0.28,0.25,0.56],'Unit','normalized','visible','on');

figcolor=get(h_f,'color');
edit2=uicontrol(h_f,'style','text','position',[150,330,300,40],...
'backgroundcolor',figcolor);%动态变化提示
button_open=uicontrol(h_f,'style','push','string','选择照片'...
,'position',[250 40 100 50],'callback','GUIopen');
button_recg=uicontrol(h_f,'style','push','string','测试准确率',...
'position',[100 40 100 50],'callback','face');
button_match=uicontrol(h_f,'style','push','string','图像匹配',...
'position',[400 40 100 50],'callback','GUIrecg');


人脸训练(face.m)

在人脸训练中,nperson表明了训练样本中含有的含有的人数,设定读取的人脸矩阵的大小为imgrow*imgcol,这个文件主要阐明了人脸训练的步骤

clc;
clear;
npersons=40;%选取40个人的脸
global imgrow;
global imgcol;%读取图像的列
global edit2
imgrow=112;
imgcol=92;%读取的图像为112*92

set(edit2,'string','读取训练数据....')%显示在句柄为edit2的文本框里
drawnow  %更新窗口的内容,不然程序结束时才会显示,这样只能看到最后一句
f_matrix=ReadFace(npersons,0);%读取训练数据
nfaces=size(f_matrix,1);%样本人脸的数量

%低维空间的图像是(npersons*5)*k的矩阵,每行代表一个主成分脸,每个脸20维特征

set(edit2,'string','训练数据PCA特征提取...')
drawnow
mA=mean(f_matrix);%求每个属性的均值
k=20;%降维至20维
[pcaface,V]=fastPCA(f_matrix,k,mA);%主成分分析法特征提取
%pcaface是200*20

set(edit2,'string','训练特征数据规范化....')
drawnow %每次设置完之后要更新窗口内容
lowvec=min(pcaface);
upvec=max(pcaface);
scaledface=scaling(pcaface,lowvec,upvec);

set(edit2,'string','SVM样本训练...')
drawnow %每次设置完之后要更新窗口内容
gamma=0.0078;
c=128;
multiSVMstruct=multiSVMtrain(scaledface,npersons,gamma,c);
%save('recognize.mat','multiSVMstruct','npersons','k','mA','V','lowvec','upvec');

set(edit2,'string','读取测试数据...')
drawnow
[testface,realclass]=ReadFace(npersons,1);

set(edit2,'string','测试数据降维...')
drawnow
m=size(testface,1);
for i=1:m
testface(i,:)=testface(i,:)-mA;
end
pcatestface=testface*V;

set(edit2,'string','测试特征数据规范化...')
scaledtestface=scaling(pcatestface,lowvec,upvec);

set(edit2,'string','样本分类...')
drawnow
class=multiSVM(scaledtestface,multiSVMstruct,npersons);

set(edit2,'string','测试完成!')
accuracy=sum(class==realclass)/length(class);
msgbox(['识别准确率:',num2str(accuracy*100),'%。'])


训练数据(ReadFace.m)

这个文件主要作用是读取训练数据,flag =0是训练样本,flag=1是测试样本。首先设置好训练集的路径,我这里是G:\资料\学习资料\Matlab\人脸库\s1到s40中每个文件夹中有10张人脸图片,这段代码的含义是从s1读到s40,每个文件夹读取其中的前5张图片作为训练样本。最后将所有的人脸样本都保存在f_matrix中

function [f_matrix,realclass]=ReadFace(npersons,flag)
%读取ORL人脸库照片里的数据到矩阵
%输入:
%    npersons-需要读入的人数,每个人的前五幅图为训练样本,后五幅为验证样本
%    imgrow-图像的行像素为全局变量
%    imgcol-图像的列像素为全局变量
%    flag-标志,0表示读入训练样本,1表示读入测试样本
%输出:
%已知全局变量:imgrow=112;imgcol=92;
global imgrow;
global imgcol;
realclass=zeros(npersons*5,1);%zeros 创建全零数组 矩阵创建了一个200*1的零矩阵
f_matrix=zeros(npersons*5,imgrow*imgcol);%创建了一个200*(112*92)的零矩阵,把训练集中所有的人脸都放在这个f_matrix中
for i=1:npersons
facepath='G:\资料\学习资料\Matlab\人脸库\s';%训练样本集的路径
facepath=strcat(facepath,num2str(i));%strcat 字符串拼接 num2str()把数字转为字符串
facepath=strcat(facepath,'\');
cachepath=facepath;%得到图片的路径
for j=1:5
facepath=cachepath;
if flag==0 %读入训练样本的数据(matlab中=相当于赋值,==才是比较)
facepath=strcat(facepath,'0'+j);
else %读入测试样本数据
facepath=strcat(facepath,num2str(5+j));
realclass((i-1)*5+j)=i;
end
facepath=strcat(facepath,'.pgm');
img=imread(facepath);
f_matrix((i-1)*5+j,:)=img(:)';%img(:)转换成112*92行1列
end
end
end


利用PCA提取样本的特征向量和降维(fastPCA.m)

PCA的计算原理:

1. 求平均人脸矩阵:

Xi代表的是一张人脸矩阵

平均人脸矩阵(平均脸)

mA=1n∑i=0nXi

2.求协方差矩阵

T=1n∑i=0n(Xi−mA)(Xi−mA)T

Z=(A-repmat(mA,m,1))

3.求协方差中最大前k个特征向量,利用eigs函数,[V,D]=eigs(T,k),其中V是特征向量,D是特征值(PCA的核心思想就是利用前K个特征向量来代表整个矩阵,达到了降维的效果)

4.V=Z’*V,pcaA=Z*V,降维。

function [pcaA,V]=fastPCA(A,k,mA)
%快速PCA,主成分分析
%输入:
%    A-样本矩阵,每行是一个样本,列是样本的维数
%    k-降至k维
%     MA 矩阵均值
%输出:
%   pcaA-降维后的k维样本特征向量组成的矩阵,即主成分
%   V-主成分分量
m=size(A,1);%计算有多少个样本
Z=(A-repmat(mA,m,1));%remat复制和平铺矩阵,原矩阵与均值矩阵相减
T=Z*Z';%求协方差矩阵,如果是z'*z则计算的维数为imgrow*imgcol>>npersons*5,∑(x-u)(x-u)'求协方差矩阵,T为200*200
[V,D]=eigs(T,k);%计算T的最大k个特征值和特征向量,V为特征向量,D为特征值,V为200*20
V=Z'*V;%协方差矩阵的特征向量(V是imgrow*imgcol*k)
for i=1:k  %特征向量单位化 该向量除以该向量的单位长度
l=norm(V(:,i));%求向量的二范数
V(:,i)=V(:,i)/l;
end
pcaA=Z*V;  %线性变换,降至k维 特征脸对人脸的表示(pcaA是npersons*5*k)
end


下一篇博客继续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  人脸识别 matlab PCA