基于PCA的人脸识别

基于PCA的人脸识别基于PCA的人脸识别(MATLAB实现)

实验简介

使用PCA通过MATLAB实现简单的人脸识别。使用的是ORL人脸库,里面共40个人,每人10张照片。主要通过两种分组方式来实现人脸识别。

  • 分组一:每个人的任意 5/8 张照片作为训练并作为测试样本库,其它 5/2 张作为测试待识别图片。
  • 分组二:前 30/38 个人作为训练,后 10/2 个人作为测试,其中测试库中每个人的任意 5/8 张照片为测试样本库,其它 5/2 张照片作为待识别图片。

PCA算法分析

分组一流程图分组一流程图
分组二流程图在这里插入图片描述
主成分分析法(PCA)又称特征脸方法,实质是通过K-L变换来实现的。PCA的目的是使各个维度上的方差尽可能大,不同维度间的相关性尽可能小,以使降维同时最大程度保持数据原始特征。以上是我对使用PCA进行人脸识别的两种分组的大致步骤框图,可能表述不准确。

PCA实现具体步骤

构造特征空间

  1. 选择n张图片进行训练,每张图片的像素值为ab(c=ab);
  2. 将每张图片的ab矩阵以列转换成c1的向量,构成n列的矩阵X(c*n);
  3. 对矩阵X进行均值、中心化操作,并求得协方差矩阵;
  4. 求取协方差矩阵的特征值,并选取k个特征值(k:取决于定义的条件。如,本文采取的是使累计贡献率>95%的数量),得到k个特征向量V(特征脸);
  5. 将k个特征向量合并成特征空间W(c*k)(分组一与分组二在此步骤有别)。

识别

  1. 测试样本投影到特征子空间,得到一组投影系数(相当于一个位置坐标,一组坐标对应一张图,同样一张图能找到一组对应的坐标);
  2. 将其与特征空间中的点求欧氏距离,距离最近的即为相似度最高的。

PCA方法的优劣

优势

  • 把人脸作为一个整体来编码,不关心眼、鼻、嘴等单个特征,大大降低识别的复杂度;
  • 图像的原始灰度数据可直接原来学习和识别,不需要处理;
  • 可消除评价指标之间的相关影响;

劣势

  • 需要计算协方差矩阵,计算量大,没有快速算法;
  • 忽略贡献率小的成分可能会引起较大误差,所忽略的可能刚好包括了重要的信息。

实验步骤

训练

  1. 将库里的400张图片(40*10)分成两组,一组作为训练,一组作为测试,并将照片按顺序重命名。具体的训练方式可分为以下两种:
  • 每个人的任意 5/8 张照片作为训练并作为测试样本库,其它 5/2 张作为测试待识别图片。(详见图1-1)
  • 前 30/38 个人作为训练,后 10/2 个人作为测试,其中测试库中每个人的任意 5/8 张照片为测试样本库(与特征脸矩阵构成特征脸空间),其它 5/2 张照片作为待识别图片。(详见图1-2)
  1. 库照片处理
    1. 将每一张库的照片转化成 N 维的向量,然后把这些向量存入一个矩阵里。可将这 200个向量以列的形式存在矩阵里。即
      X=[x1 x2 … x200]
    2. 将这 200 个向量的每个元素相加起来求出平均值。再用 X 里的每一个向量减去这个平均值得到每个的偏差。
      平均值在这里插入图片描述
      偏差在这里插入图片描述
      最后得到在这里插入图片描述
    3. 中心化并计算协方差矩阵。
    4. 利用协方差矩阵进行主成分分析,提取特征脸,获取训练样本特征数据。

测试

对于测试样本,读取图像,将其变换至PCA空间,利用近邻法识别。

计算识别准确率

对待识别的每一张照片进行测试,与训练样本库中的每一张照片进行比对,若得到的最小距离的照片与待识别的照片为同一组(根据输入的每组照片训练数目判断),则标记为正确。定义准确率公式为正确数/总待识别数。

显示结果

  1. 对每一幅测试图像显示距离排名在前三位的识别结果;
  2. 显示前五张特征脸;
  3. 显示识别准确率折线图。

核心代码

分组一

  • 训练:将照片分为两类,一类作为测试,一类作为训练。
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global W               %特征脸空间
global V               %特征脸
global img_pj          %均值
global wts             %训练的样本总数
global train_num       %每个人训练的照片
n = 1;
p=1;
%分成train和test两个文件夹,并且图片重命名
for i=1:40                                %40个人
    a=1:10;                               %每个人10张
    Ind = a(:,randperm(size(a,2)));       %size:取矩阵的列数  randperm:打乱顺序
    for h = 1:train_num  
        j= Ind(1,h);
        File=['人脸库地址',sprintf('%d',i),'\',sprintf('%d',j),'.pgm'];
        Filesave=['训练集地址','\',sprintf('%03d',p),'.pgm'];
        copyfile(File,Filesave)
        p = p + 1;                        %训练样本总数
    end
    for h = train_num+1:10  
        j= Ind(1,h);
        File=['人脸库地址',sprintf('%d',i),'\',sprintf('%d',j),'.pgm'];
        Filesave=['测试集地址','\',sprintf('%03d',n),'.pgm'];
        copyfile(File,Filesave)
        n = n + 1;                         %测试样本总数
    end
end
%批量读取指定文件夹下的图片
path = uigetdir;                         %打开一个模态对话框
img_path = dir(strcat(path,'\*.pgm'));   %列出.pgm文件
img_num = length(img_path);              %img_num:文件夹中的总数
imagedata = [];                          %一张图片为一列
if img_num >0
    for j = 1:img_num
        img_name = img_path(j).name;
        temp = imread(strcat(path, '/', img_name));
        temp = double(temp(:));
        imagedata = [imagedata, temp];
    end
end
%中心化并计算协方差矩阵
wts = size(imagedata,2);                        %imagedata的列数(等于训练的样本数)
img_pj= mean(imagedata,2);                      %均值
for i = 1:wts
    imagedata(:,i) = imagedata(:,i) - img_pj;   %中心化
end
covMat = imagedata'*imagedata; %':转置

[COEFF, latent, explained] = pcacov(covMat);
%留下使累计贡献量达95%的k个特征向量
i = 1;
proportion = 0;
while(proportion < 95)
    proportion = proportion + explained(i);
    i = i+1;
end
k = i - 1;
%求出原协方差矩阵的特征向量,即特征脸
V = imagedata*COEFF;          % N*MV = V(:,1:k);    
%显示前5的特征脸
A=reshape(V(:,1),[112 92]);   %每张图片大小为112*92
A=mat2gray(A);
axes( handles.axes1 )
imshow([A])
B=reshape(V(:,2),[112 92]);
B=mat2gray(B);
axes( handles.axes2 )
imshow([B])
C=reshape(V(:,3),[112 92]);
C=mat2gray(C);
axes( handles.axes3 )
imshow([C])
D=reshape(V(:,4),[112 92]);
D=mat2gray(D);
axes( handles.axes4 )
imshow([D])
E=reshape(V(:,5),[112 92]);
E=mat2gray(E);
axes( handles.axes5 )
imshow([E])
% 训练样本在 PCA 特征空间下的表达矩阵 k*M
W= V'*imagedata;
msgbox(['训练完成'])
  • 识别:选择test文件中的照片进行识别,选取距离前三近的图片呈现。
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global im;
[filename, path] = uigetfile({ 
   '*.pgm'},'choose photo');
str = [path, filename];
im = imread(str);
axes( handles.axes6);
imshow(im);

% --- Executes on button press in pushbutton3.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global im        %待识别的图片
global V
global W
global img_pj
global wts
im1 = double(im(:));
objectone = V'*(im1 - img_pj);              %计算待识别图片的投影
%最小距离法,寻找和待识别图片最为接近的训练图片
for k = 1:wts
    temp1(k) = norm(objectone - W(:,k));    %欧氏距离
end
[s_temp,id]=sort(temp1,'ascend');           %筛选出距离前三小的
axes( handles.axes7 )
imshow(['训练集地址','\',sprintf('%03d',id(1)),'.pgm'])
axes( handles.axes8 );
imshow(['训练集地址','\',sprintf('%03d',id(2)),'.pgm'])
axes( handles.axes9 )
imshow(['训练集地址','\',sprintf('%03d',id(3)),'.pgm'])
  • 准确率:准确率=正确数/待识别总数,对test文件中的照片进行遍历。
function pushbutton4_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton4 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global V
global W
global train_num
col_of_data = 40*train_num;              
pathname = uigetdir;
img_path_list = dir(strcat(pathname,'\*.pgm'));
img_num = length(img_path_list);
testdata = [];
if img_num >0
    for j = 1:img_num
        img_name = img_path_list(j).name;
        temp = imread(strcat(pathname, '/', img_name));
        temp = double(temp(:));
        testdata = [testdata, temp];
    end
end
col_of_test = size(testdata,2);            %col_of_test:待测样本数
img_pj= mean(testdata,2);   
for i = 1:size(testdata,2)
    testdata(:,i) = testdata(:,i) - img_pj;  
end
object =V'* testdata;
num = 0;
for j = 1:col_of_test
    distance = 1e8;
    for k = 1:col_of_data                 %col_of_data:训练样本总数
        temp = norm(object(:,j) - W(:,k));
        if(distance>temp)
            aimone = k;                   %取出距离最小的
            distance = temp;
        end
    end
        if ceil(j/(10-train_num))==ceil(aimone/(train_num))
            num = num + 1;                %TP:预测和真实值都为1
        end
end
accuracy = num/col_of_test;
set(handles.edit2,'String',num2str(accuracy)); 
  • 折线图:显示准确率曲线
x=2:1:9;
a=[0.74375,0.85,0.89167,0.915,0.93125,0.95,0.96245,1]; %数据
plot(x,a,'-*b');                                       %线性,颜色,标记
axis([2,9,0.7,1])  
set(gca,'XTick',[2:1:9]) 
set(gca,'YTick',[0.7:0.05:1]) 
xlabel('训练数目(n/10)')  
ylabel('准确率(%)') 
  • 新建、删除文件夹:照片分组的文件夹
% 新建train和test文件夹
% --- Executes on button press in pushbutton6.
function pushbutton6_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton6 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
cd('C:\Users\Administrator\Desktop\实验四');
mkdir train; 
mkdir test;
%删除文件夹
% --- Executes on button press in pushbutton7.
function pushbutton7_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton7 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
cd('C:\Users\Administrator\Desktop\实验四');
%delete('*.pgm') 
rmdir train s
rmdir test s

分组二

  • 训练:将照片分为三类,一类为train(训练),一类为yanzheng(验证集,与特征脸V生成特征空间W),一类为test(待识别)。生成V的方式与分组一相同,注意图片选取问题即可;生成W1(W1= V’*imagedata1)的imagedata1为验证集中的照片。以下仅为照片分组与生成W1的代码。
%分成train、test、yanzheng三个文件夹,并且图片重命名
for i=1:train_num                         %前n个人
    a=1:10;                               %每个人10张
    Ind = a(:,randperm(size(a,2)));       %size:取矩阵的列数  randperm:打乱顺序
    for h = 1:10 
        j= Ind(1,h);
        File=['人脸库地址',sprintf('%d',i),'\',sprintf('%d',j),'.pgm'];
        Filesave=['训练集地址','\',sprintf('%03d',p),'.pgm'];
        copyfile(File,Filesave)
        p = p + 1;                        %训练样本总数
    end
end
for i=train_num+1 :40                     %40-n个人的前5张
    a=1:10;                                
    Ind = a(:,randperm(size(a,2)));  
    for h = 1:5  
        j= Ind(1,h);
        File=['人脸库地址',sprintf('%d',i),'\',sprintf('%d',j),'.pgm'];
        Filesave=['验证集地址','\',sprintf('%03d',m),'.pgm'];
        copyfile(File,Filesave)
        m = m + 1;                         %测试样本总数
    end
    for h = 6:10  
        j= Ind(1,h);
        File=['人脸库地址',sprintf('%d',i),'\',sprintf('%d',j),'.pgm'];
        Filesave=['测试集地址','\',sprintf('%03d',n),'.pgm'];
        copyfile(File,Filesave)
        n = n + 1;                         %待识别总数
    end
End


% --- Executes on button press in pushbutton5.
function pushbutton5_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton5 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
global V
global W1
global img_pj1
%批量读取指定文件夹下的图片
path = uigetdir;                         %打开一个模态对话框
img_path = dir(strcat(path,'\*.pgm'));   %列出.pgm文件
img_num = length(img_path);              %img_num:文件夹中的总数
imagedata1 = [];                          %一张图片为一列
if img_num >0
    for j = 1:img_num
        img_name = img_path(j).name;
        temp = imread(strcat(path, '/', img_name));
        temp = double(temp(:));
        imagedata1 = [imagedata1, temp];
    end
end
 
%中心化并计算协方差矩阵
wts = size(imagedata1,2);                        %imagedata的列数(等于训练的样本数)
img_pj1= mean(imagedata1,2);                      %均值
for i = 1:wts
    imagedata1(:,i) = imagedata1(:,i) - img_pj1;   %中心化
end
size(imagedata1)
% 训练样本在 PCA 特征空间下的表达矩阵 k*M
W1= V'*imagedata1;
msgbox(['训练2完成'])

实验结果

在这里插入图片描述
在这里插入图片描述

说明

以上仅个人拙见,欢迎共同学习交流。

源码

今天的文章基于PCA的人脸识别分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/32927.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注