PCA人脸识别(带matlab程序)
前几天上数字图像处理的时候学习了PCA人脸识别,趁热打铁,做一些学习记录。PCA(Principal Component Analysis)是一种常用的数据分析方法。PCA通过线性变换将原始数据变换为一组各维度线性无关的表示,可用于提取数据的主要特征分量,常用于高维数据的降维。在人脸识别上面,用PCA的主要目的就是把原来维度很高的图像,提取图像的主要成分(用于识别的特征),去掉不重要的成分,使得可以用比较少的维度来表示图像,以方便进行图形识别。
一个非常不错的学习PCA资料PCA数学原理。
看完这个应该对PCA 的原理有了更深刻的认识。
下面是matlab代码
%
%测试数据:40人,每人10张照片。每人取前ph张照片作为训练集,后(10-ph)张照片作为测试集。
clear;
clc;
ph=6;
%%
%第一步:计算特征脸并创建特征空间
tic %计算运行时间
%申请录入数据矩阵内存
imdata=zeros(112*92,40*ph);
for i=1:40
for j=1:ph
% addr=strcat('G:/orl_face/s',num2str(i),'/',num2str(j),'.pgm');
addr=strcat('G:/orl_face/s',num2str(i),'/',num2str(j),'.pgm');
a=imread(addr);%从地址中读入图像
b=a(1:112*92); %把图像a矩阵按列顺序转为行向量b
imdata(:,ph*(i-1)+j)=b'; %把b的转置矩阵存放到imdata矩阵的第ph*(i-1)+j列
end;
end;
%计算平均脸
imaverage=mean(imdata,2); %按行求平均mean(a,2) 按列mean(a)
%显示平均脸
%向量矩阵化
out=reshape(imaverage,112,92);
figure;
subplot(1,1,1);
imshow(out,[]);
title(strcat('MeanFace'));
clear i j a b addr
%图像预处理
immin=zeros(112*92,40*ph);
for i=1:40*ph
%归一化处理,提升矩阵计算速度,但小数精度不够,会影响匹配率
%immin(:,i) = (imdata(:,i)-imaverage)/col2medivation(imdata(:,i)-imaverage,112*92);
%仅减去平均脸,不做归一化处理
immin(:,i) = imdata(:,i)-imaverage;
end;
clear i imdata
%%
%计算协方差矩阵
% W=immin*immin';%dxn*nxd =dxd 太大
k=32;
W=immin'*immin; %n*d x d*n= n*n 较小
%计算特征向量与特征值(向量)
[V,~]=eigs(W,k);%降到k维
%对特征向量进行排序
V=immin*V; %dxn*nxk=d*k
VT=fliplr(V);
clear V W
%显示前32个特征脸
figure;
for i=1:32
v=VT(:,i);
%向量矩阵化
out=reshape(v,112,92); %把(112*92)x1的列向量转成112x92的矩阵
subplot(4,8,i);
imshow(out,[]);
title(strcat('Face',num2str(i)));
end;
clear i v out
%%
%第二步:映射训练集图像到特征空间
%申请训练数据矩阵内存
featuretrain=zeros(k,40*ph);
for i=1:40*ph;
%映射训练集图像
add=VT'*immin(:,i); %k*d x d*1=k*1;
featuretrain(:,i)=add;
end;
clear i add
%%
%第三步:映射测试集图像到特征空间
%申请录入数据矩阵内存
test=zeros(112*92,40*(10-ph));
for i=1:40
for j=(ph+1):10 %3到10
addr=strcat('G:/orl_face/s',num2str(i),'/',num2str(j),'.pgm');
a=imread(addr);
b=a(1:112*92);
test(:,(10-ph)*(i-1)+(j-ph))=b';
end;
end;
%图像预处理
testmin=zeros(112*92,40*(10-ph));
for i=1:40*(10-ph)
testmin(:,i) = test(:,i)-imaverage;
end;
clear i j a b addr test
%申请测试数据矩阵内存
featuretest=zeros(k,40*(10-ph));
for i=1:40*(10-ph);
%映射测试集图像
add=VT'*testmin(:,i);
featuretest(:,i)=add;
end;
clear i add
%%
%匹配计算
count=0;
for t=1:40*(10-ph)
point=figureNum(featuretest,t,featuretrain,40*ph);
%计算匹配个数
if(round(point/ph+0.4)==round(t/(10-ph)+0.4))
count=count+1;
end;
end;
tol=count/(40*(10-ph));
clear count point t
display(strcat('匹配率:',num2str(tol*100),'%'));
clear ph tol
toc
figureNum( test,t1,train,num)函数,用于计算最小距离。
function point = figureNum( test,t1,train,num)
%UNTITLED2 Summary of this function goes here
% Detailed explanation goes here
point=1;
T=norm(test(:,t1)-train(:,1));%初始默认第一列最匹配
for t2=1:num
distance=norm(test(:,t1)-train(:,t2));
if (distance<T)
point=t2;
T=distance;
end;
end;
end
平均脸:
特征脸:
以上使用的是orl人脸库,取每人前6张共40*6张图像作为训练样本,其他的图片作为测试样本,取前32个主成分匹配率是90%.
下面是使用yale库的测试情况,程序只要稍微改一下
%
%测试数据:15人,每人11张照片。每人取前ph张照片作为训练集,后(11-ph)张照片作为测试集。
clear;
clc;
ph=7;
%%
%第一步:计算特征脸并创建特征空间
tic %计算运行时间
%申请录入数据矩阵内存
imdata=zeros(100*100,15*ph);
for i=1:15
for j=1:ph
% addr=strcat('G:/orl_face/s',num2str(i),'/',num2str(j),'.pgm');
addr=strcat('G:/yale/s',num2str(i),'/s',num2str(j),'.bmp');
a=imread(addr);%从地址中读入图像
b=a(1:100*100); %把图像a矩阵按列顺序转为行向量b
imdata(:,ph*(i-1)+j)=b'; %把b的转置矩阵存放到imdata矩阵的第ph*(i-1)+j列
end;
end;
%计算平均脸
imaverage=mean(imdata,2); %按行求平均mean(a,2) 按列mean(a)
%显示平均脸
%向量矩阵化
out=reshape(imaverage,100,100);
figure;
subplot(1,1,1);
imshow(out,[]);
title(strcat('MeanFace'));
clear i j a b addr
%图像预处理
immin=zeros(100*100,15*ph);
for i=1:15*ph
%归一化处理,提升矩阵计算速度,但小数精度不够,会影响匹配率
%immin(:,i) = (imdata(:,i)-imaverage)/col2medivation(imdata(:,i)-imaverage,112*92);
%仅减去平均脸,不做归一化处理
immin(:,i) = imdata(:,i)-imaverage;
end;
clear i imdata
%%
%计算协方差矩阵
% W=immin*immin';%dxn*nxd =dxd 太大
k=20;%k要小于等于ph*15(n)
W=immin'*immin; %n*d x d*n= n*n 较小
%计算特征向量与特征值(向量)
[V,~]=eigs(W,k);%降到k维
%对特征向量进行排序
V=immin*V; %dxn*nxk=d*k
VT=fliplr(V);
clear V W
%显示前20个特征脸
figure;
for i=1:k
v=VT(:,i);
%向量矩阵化
out=reshape(v,100,100); %把(100*100)x1的列向量转成100x100的矩阵
subplot(4,5,i);
imshow(out,[]);
title(strcat('Face',num2str(i)));
end;
clear i v out
%%
%第二步:映射训练集图像到特征空间
%申请训练数据矩阵内存
featuretrain=zeros(k,15*ph);
for i=1:15*ph;
%映射训练集图像
add=VT'*immin(:,i); %k*d x d*1=k*1;
featuretrain(:,i)=add;
end;
clear i add
%%
%第三步:映射测试集图像到特征空间
%申请录入数据矩阵内存
test=zeros(100*100,15*(11-ph));
for i=1:15
for j=(ph+1):11 %ph+1到11
addr=strcat('G:/yale/s',num2str(i),'/s',num2str(j),'.bmp');
a=imread(addr);
b=a(1:100*100);
test(:,(11-ph)*(i-1)+(j-ph))=b';%把b的转置矩阵存放到test矩阵的第(11-ph)*(i-1)+(j-ph)列
end;
end;
%图像预处理
testmin=zeros(100*100,15*(11-ph));
for i=1:15*(11-ph)
testmin(:,i) = test(:,i)-imaverage;
end;
clear i j a b addr test
%申请测试数据矩阵内存
featuretest=zeros(k,15*(11-ph));
for i=1:15*(11-ph);
%映射测试集图像
add=VT'*testmin(:,i);
featuretest(:,i)=add;
end;
clear i add
%%
%匹配计算
count=0;
for t=1:15*(11-ph)
point=figureNum(featuretest,t,featuretrain,15*ph);
%计算匹配个数
if(round(point/ph+0.4)==round(t/(11-ph)+0.4))
count=count+1;
end;
end;
tol=count/(15*(11-ph));
clear count point t
display(strcat('匹配率:',num2str(tol*100),'%'));
clear ph tol
toc
平均脸
特征脸
每个人取7张图片作为训练样本,3张作为测试样本,匹配率是86.6667%。