matlab实现人脸识别---PCA与最近邻法

目标:已知类别的人脸图像,待检类别图像,从待检测图像中识别与已知类别的图像中相同的图像。

已知类别:3479张

待检测类别:276张

PCA给样本矩阵降维

最近邻法识别

一共包括3个.m文件,train.m,test.m,recognition.m。

train.m文件实现将训练样本矩阵降维,并得到映射矩阵;test.m文件将测试样本矩阵降维;recognition.m文件实现识别过程。

train.m代码:

file_path='F:\课程\模式识别\Dataset\muct人脸图像\已知类别\';% 图像文件夹路径 
img_path_list = dir(strcat(file_path,'*.jpg'));%获取该文件夹中所有jpg格式的图像
img_num = length(img_path_list);%获取图像总数量
imgTrain = [];
Q = [];%列矩阵,一副图像
trainFace = [];%降维后的训练样本的矩阵
% 读取每一幅图像
%转化为灰度图像 并将每一幅图像转化为列向量 然后合并为矩阵T
for j=1:img_num %逐一读取图像
    image_name = img_path_list(j).name;%图像名
    img = imread(strcat(file_path,image_name));              
    img = rgb2gray(img);%转为灰度   
    %img=histeq(img);%直方图均衡化
    img=imadjust(img);%使得图像中 1% 的数据饱和至最低和最高亮度
    img = imresize(img, 0.2, 'nearest');
     [irow,icol] = size(img);%得到图片大小
%     for m=1:irow
%         for n=1:icol
%             img(m,n) = 10*img(m,n);
%         end
%     end
    temp = reshape(img,irow*icol,1);%将二维图片转为一维向量
    Q = [Q,temp]; % 每张图片的信息做为V的一列  

    imgTrain=[imgTrain,temp];
   
end

%  [L_eig_vec,A] = HSCalPCA(imgTrain);%调用PCA降维函数,得到映射矩阵

%得到均值矩阵
%并用T剪去均值矩阵  得到矩阵A
 m = mean(imgTrain,2); % 平均图像/行平均(每一副图像的对应象素求平均)m=(1/P)*sum(Tj's) (j=1 : P)
Train_Number = size(imgTrain,2);%列数
%计算机每一张图片到均值图像的方差
A = [];  
for i = 1 : Train_Number%对每一列
    temp = double(imgTrain(:,i))-m; %每一张图与均值的差异
    A = [A temp]; %差矩阵
end
%得到A的协方差矩阵并转置得到L
L = A'*A; % L是协方差矩阵C=A*A'的转置
%得到特征值与特征向量
[V D] = eig(L); %对角线上的元素是L|C的特征值.V:以特征向量为列的满秩矩阵,D:特征值对角矩阵。即L*V = V*D.
L_eig_vec = [];%特征值向量
max=0;
for i = 1 : size(V,2)%对每个特征向量   
   max=max+D(i,i);
end
sum=0;
for i = size(V,2):-1:size(V,2)-2%对每个特征向量      
    L_eig_vec = [L_eig_vec V(:,i)]*0;%集中对应的特征向量
    sum=sum+D(i,i);
end
for i = size(V,2)-3:-1:size(V,2)-9%对每个特征向量      
    L_eig_vec = [L_eig_vec V(:,i)]*0.05;%集中对应的特征向量
    sum=sum+D(i,i);
end
for i = size(V,2)-10:-1:1%对每个特征向量      
    L_eig_vec = [L_eig_vec V(:,i)];%集中对应的特征向量
    sum=sum+D(i,i);
    if(sum/max>0.99)
        break;
    end
end

% for i = 1:size(V,2)
%      if(D(i,i)>1)
% L_eig_vec = [L_eig_vec V(:,i)];
%     end
% end

Eigenfaces = A * L_eig_vec; % 计算机协方差矩阵C的特征向量,
                            %得到降维了的特征,A为每一张图像与均值图像的方差构成的矩阵,
TrainProjectedImages = [];%映射图像
for i = 1 : img_num%对于每一个训练特征
    temp = Eigenfaces'*double(Q(:,i));
    TrainProjectedImages = [TrainProjectedImages temp];  %得到 L_eig_vec;
end
save('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TrainProjectedImages.mat','TrainProjectedImages');
save('D:\Program Files\MATLAB\R2016a\bin\projects\face1\Eigenfaces.mat','Eigenfaces');


test.m:

TrainProjectedImages=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TrainProjectedImages.mat');
TrainProjectedImages=TrainProjectedImages.TrainProjectedImages;%训练数据集(降维后的) 
Eigenfaces=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\Eigenfaces.mat');
Eigenfaces=Eigenfaces.Eigenfaces;%训练数据集(降维后的) 
% imgTrain=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\imgTrain.mat');
% imgTrain=imgTrain.imgTrain;%训练数据集(降维后的)
file_path='F:\课程\模式识别\Dataset\muct人脸图像\待分类\';% 图像文件夹路径 
img_path_list = dir(strcat(file_path,'*.jpg'));%获取该文件夹中所有jpg格式的图像
img_num = length(img_path_list);%获取图像总数量
imgTest = [];
Q = [];%列矩阵,一幅图像
testFace = [];%减去训练矩阵均值后的测试图像矩阵
%导入由训练数据集得到的  变换矩阵跟降维后的训练集

% 读取每一幅图像
%转化为灰度图像 并将每一幅图像转化为列向量 然后合并为矩阵T
for j=1:img_num %逐一读取图像
    image_name = img_path_list(j).name;%图像名
    img = imread(strcat(file_path,image_name));              
    img = rgb2gray(img);%转为灰度   
    %img=histeq(img);%直方图均衡化
    img=imadjust(img);%使得图像中 1% 的数据饱和至最低和最高亮度
     img = imresize(img, 0.2, 'nearest');%改变图像的大小,'nearest'(默认值)最近邻插值
    [irow,icol] = size(img);%得到图片大小
%     for m=1:irow
%         for n=1:icol
%             img(m,n) = 10*img(m,n);
%         end
%     end
    temp = reshape(img,irow*icol,1);%将二维图片转为一维向量
    Q = [Q,temp]; % 每张图片的信息做为V的一列  
   
    imgTest = [imgTest,temp];
   
end
%     imgTrain = imgTrain';
%     mMiu = mean(imgTrain,2);%求各行的均值
%     
%     mMiu = repmat(mMiu,1,icol);%复制成原有的行数N列的矩阵
%     testFace =double(imgTest')-mMiu;


TestProjectedImages = [];%测试集降维
for i = 1 : img_num%对于每一个训练特征
    temp = Eigenfaces'*double(Q(:,i));
    TestProjectedImages = [TestProjectedImages temp];  %得到 L_eig_vec;
end
% TsetProjectedImages1=trainFace*double(testFace' );
  save('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TestProjectedImages.mat','TestProjectedImages');
% save('D:\Program Files\MATLAB\R2016a\bin\projects\face\testFace.mat','testFace');


recognition.m:
clc;
clear;
m=0;
count=0;
% 加载降维后的样本和测试矩阵,进行最近邻法识别
TrainProjectedImages=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TrainProjectedImages.mat');
TrainProjectedImages=TrainProjectedImages.TrainProjectedImages;%训练数据集(降维后的) *3479
TestProjectedImages=load('D:\Program Files\MATLAB\R2016a\bin\projects\face1\TestProjectedImages.mat');
TestProjectedImages=TestProjectedImages.TestProjectedImages;%测试数据集(降维后的)    *276
[Trainrows,Traincols] = size(TrainProjectedImages);%得到训练集的大小
[Testrows,Testcols] = size(TestProjectedImages);%得到测试集的大小
%将训练图片的名字存到以为矩阵里
img_name_train = [];
img_name_test = [];
file_path_train= 'F:\课程\模式识别\Dataset\muct人脸图像\已知类别\';
img_path_list_train = dir(strcat(file_path_train,'*.jpg'));
img_num_train = length(img_path_list_train);
% for k=1:img_num_train
% 	name2 = img_path_list_train(k).name;
%     img_name_train = [img_name_train,name2];
% end
%将测试图片的名字存到一维矩阵里
file_path_test= 'F:\课程\模式识别\Dataset\muct人脸图像\待分类\';
img_path_list_test = dir(strcat(file_path_test,'*.jpg'));
img_num_test = length(img_path_list_test);

% for g=1:img_num_test
% 	name1= img_path_list_test(g).name;
%     img_name_test = [img_name_test,name1];
% end
%循环,计算每张测试图片与训练图片的距离,找到距离最小的测试图,判断测试图片与训练图片名字是否一致,一致数量加一
for i=1:Testcols
    mImgTestCur = TestProjectedImages(:,i);
    vDisMin = 9999999999999;
    vClassMin = -1;
    for j=1:Traincols
        mImgTrainCur = TrainProjectedImages(:,j);
        mDis = mImgTestCur-mImgTrainCur;
        mDis = mDis.^2;
        vDis = sqrt(sum(mDis));
        if vDis<vDisMin
            vDisMin = vDis;
		    m=j;
        end
    end
    name1=img_path_list_train(m).name;
   name1 =name1(2:4);%取名字的第2到4位置的字符
   name1=str2num(name1);
    name2=img_path_list_test(i).name;
     name2 =name2(2:4);
      name2=str2num(name2);
    if name2==name1
	count=count+1;
    end
       
end

vRatio = count/Testcols*100;
sprintf('正确率:%.1f%%',vRatio)



现在我们回到LDA的原理上,我们在第一节说讲到了LDA希望投影后希望同一种类别数据的投影点尽可能的接近,而不同类别的数据的类别中心之间的距离尽可能的大,但是这只是一个感官的度量。现在我们首先从比较简单的二类LDA入手,严谨的分析LDA的原理。     假设我们的数据集D={(x1,y1),(x2,y2),...,((xm,ym))}D={(x1,y1),(x2,y2),...,((xm,ym))},其中任意样本xixi为n维向量,yi∈{0,1}yi∈{0,1}。我们定义Nj(j=0,1)Nj(j=0,1)为第j类样本的个数,Xj(j=0,1)Xj(j=0,1)为第j类样本的集合,而μj(j=0,1)μj(j=0,1)为第j类样本的均值向量,定义Σj(j=0,1)Σj(j=0,1)为第j类样本的协方差矩阵(严格说是缺少分母部分的协方差矩阵)。     μjμj的表达式为: μj=1Nj∑x∈Xjx(j=0,1) μj=1Nj∑x∈Xjx(j=0,1)     ΣjΣj的表达式为: Σj=∑x∈Xj(x−μj)(x−μj)T(j=0,1) Σj=∑x∈Xj(x−μj)(x−μj)T(j=0,1)     由于是两类数据,因此我们只需要将数据投影到一条直线上即可。假设我们的投影直线是向量ww,则对任意一个样本本xixi,它在直线ww的投影为wTxiwTxi,对于我们的两个类别的中心点μ0,μ1μ0,μ1,在在直线ww的投影为wTμ0wTμ0和wTμ1wTμ1。由于LDA需要让不同类别的数据的类别中心之间的距离尽可能的大,也就是我们要最大化||wTμ0−wTμ1||22||wTμ0−wTμ1||22,同时我们希望同一种类别数据的投影点尽可能的接近,也就是要同类样本投影点的协方差wTΣ0wwTΣ0w和wTΣ1wwTΣ1w尽可能的小,即最小化wTΣ0w+wTΣ1wwTΣ0w+wTΣ1w。综上所述,我们的优化目标为: argmaxwJ(w)=||wTμ0−wTμ1||22wTΣ0w+wTΣ1w=wT(μ0−μ1)(μ0−μ1)TwwT(Σ0+Σ1)w argmax⏟wJ(w)=||wTμ0−wTμ1||22wTΣ0w+wTΣ1w=wT(μ0−μ1)(μ0−μ1)TwwT(Σ0+Σ1)w     我们一般定义类内散度矩阵SwSw为: Sw=Σ0+Σ1=∑x∈X0(x−μ0)(x−μ0)T+∑x∈X1(x−μ1)(x−μ1)T Sw=Σ0+Σ1=∑x∈X0(x−μ0)(x−μ0)T+∑x∈X1(x−μ1)(x−μ1)T     同时定义类间散度矩阵SbSb为: Sb=(μ0−μ1)(μ0−μ1)T Sb=(μ0−μ1)(μ0−μ1)T     这样我们的优化目标重写为: argmaxwJ(w)=wTSbwwTSww argmax⏟wJ(w)=wTSbwwTSww     仔细一看上式,这不就是我们的广义瑞利商嘛!这就简单了,利用我们第二节讲到的广义瑞利商的性质,我们知道我们的J(w)J(w)最大值为矩阵S−12wSbS−12wSw−12SbSw−12的最大特征值,而对应的ww为S−12wSbS−12wSw−12SbSw−12的最大特征值对应的特征向量! 而S−1wSbSw−1Sb的特征值和S−12wSbS−12wSw−12SbSw−12的特征值相同,S−1wSbSw−1Sb的特征向量w′w′和S−12wSbS−12wSw−12SbSw−12的特征向量ww满足w′=S−12www′=Sw−12w的关系!     注意到对于二类的时候,SbwSbw的方向恒为μ0−μ1μ0−μ1,不妨令Sbw=λ(μ0−μ1)Sbw=λ(μ0−μ1),将其带入:(S−1wSb)w=λw(Sw−1Sb)w=λw,可以得到w=S−1w(μ0−μ1)w=Sw−1(μ0−μ1), 也就是说我们只要求出原始二类样本的均值和方差就可以确定最佳的投影方向ww了。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值