基于PCA的人脸识别02 - 实现一个最基本的系统原型

基本框架参考了 http://blog.csdn.net/hesays/article/details/39498375

部分不是很明白的代码还参考了 http://blog.csdn.net/on2way/article/details/42390149

有的地方发现别人做得好像不对,所以就去查了另外的文章,也不知道怎么就互相综合出了现在的结果。还是遗留了很多基本原理上的问题,并没有深究,因为一旦深究就停不下来了,问题越来越多。只是基本上,基本上能实现一点简单的功能了,所以就把这个很粗糙、很简陋的系统先放上来,以后再反观自己的学习过程应该会有另外的收获。


从MATLAB入门到搞出一个简单的人脸识别系统,原来并不需要很久=。=...且看本阶段成果——


毕业设计阶段性报告·PCA最简系统实现

完成时间:2015/03/28– 2015/03/31 总结时间:2015/04/04– 2015/04/05


一、原理框图及变量间的关系


1. 原理框图:


2. 变量关系(数据流向说明):



二、具体步骤(关键变量用黄色高亮标出,与代码中的变量名称对应)

 

0. 准备好数据库:下载ORL人脸数据库,40个人,每人10张,共400张图片,图像尺寸为112x92。人为地将数据库分为训练集和测试集:将每个人的第1~5幅图像作为训练集,用于学习每个人的特征;每个人的第6~10幅图像作为测试集,即作为系统的输入,逐个判断其类别。

 (不用在文件夹里作任何实际的处理,只是对图片的两种用途心中有数就行。直接把数据库放到Matlab工作路径下,列表中显示s1, s2, s3…s40共40个文件夹)

 

1. 训练阶段:A~F

A. 读取训练集图片数据,按行存入training_set(M×N矩阵, M=200, N=112×92)

B. 计算training_set 每一列的均值,得到Mean (1×N矩阵)。将training_set 的每一行减去Mean,得到中心化的数据集X (M×N矩阵)

C. 计算协方差矩阵:Σ=XXT,记为Sigma(M×M矩阵)

D. 利用Matlab自带的函数eigs(),求出前k个特征值存入矩阵D(k×k对角方阵,对角元是特征值) 以及相应的特征向量V(M×k矩阵,每一列是一个特征向量)

[V,D]=eigs(Sigma,k);

其中k是可调的系统参数,这里暂定为k=15。这k个特征向量就是我们要找的低维空间(子空间)中的“基”,即所谓的“坐标系”。


E. 将X和特征向量矩阵V相乘,得到特征脸矩阵E(N×k矩阵,每一列代表一个特征脸,按照主成分的重要程度降序排列,从左至右,第一张脸代表最主要的数据分布方向。)

E=X’*V;

利用该特征脸矩阵,就可以对训练集、测试集进行降维了。15个特征脸显示如下:


F. 训练集降维:用原始训练集数据矩阵training_set与特征脸矩阵E相乘,得到降维后的训练集数据Train_E(M×k矩阵,比原来的M×N矩阵training_set维数大大降低)

Train_E=training_set*E;

  

2. 测试阶段:G~H

G. 测试集数据读取与降维:读取测试集数据,图片变为行向量,存入testing_set(M×N矩阵)。测试集数据矩阵testing_set与特征脸矩阵E相乘,得到降维后的测试集数据Test_E(M×k矩阵)

Test_E=testing_set*E;

H. 分类器设计与识别率计算:

①到上一步为止,降维后的训练集和测试集两组数据的形态是这样的:


②举例说明:将测试集数据Test_E逐行取出,每一行与Train_E的每一行求欧氏距离,认为它属于与之距离最近的那一类。例如,取出Test_E的第7行(测试集中第2个人的第2张图),与Train_E的所有行求距离后发现与第9行(训练集中第2个人的第4张图)最近,则判断属于第2个人(判断正确)

 

③更一般地,首先初始化correct=0用于记录系统判断正确的“得分”。取出Test_E第i行(其实我知道它属于第“i/5向上取整”个人,记为true_class,但我假装不知道,拿去考验我设计的系统能否判断正确)。将第i行与Train_E的每一行求距离(记为error1×200行向量)后,发现与第j行最近,于是系统判断这张测试图片属于第“j/5向上取整”个人,记为recog_class。如果true_class= recog_class,那么系统判断正确,加一分!

correct=correct+1;

 

④求出识别率:accuracy= correct/200;

运行程序后结果如下:


 

三、本阶段系统关键特点小结

 

1. 采用的是ORL的数据库,400个人,每人10张图片。人为地将数据库分为训练集(每个人的前5张图片)和测试集(每个人的后5张图片)。直接将原始图像的灰度值作为“降维的对象”,即所谓的“输入特征

2. 按照PCA的原理,进行均值归零、计算协方差矩阵、算特征值和特征向量、得出特征脸后,利用特征脸分别将训练集和测试集降维(目前子空间维数k=15,还没尝试其它维数)。

3. 分类器用的是最简单的“最近邻原则”,将降维后的训练集/测试集数据比较欧氏距离后,最近的就认为是同类。

4. 目前的识别率是0.77


四、下一阶段的计划

 

1. 优化已有的最简系统:

(1)求协方差矩阵时,数据量庞大;可用“SVD原理”等方法,提升速度;对比优化前后的程序运行时间。

(2)目前子空间的维数选为k = 15,准确率达77%。尝试不同的k值,观察随着k的上升,准确率是如何达到饱和的;选择一个能较好地兼顾速度和准确率的k。

(3)分类器选用了最基本的“最近邻准则”,尝试别的分类器,例如三阶近邻,看能否提高准确率。

 

2. 选做:

(1)参考cai deng老师的主页,看算法或者代码本身有没有可以改进的地方。

(2)深入理解PCA:“人脸重建”?

 

3. 进阶研究:(中期检查之前)

(1)试用另一个人脸数据库(Yale),有比较明显的光照变化,感觉单纯的PCA会杯具

(2)选择不同的输入特征:HOG, LBP, …(也许可以克服光照的影响?)

(3)核心算法由PCA改为LDA会如何?

 

五、目前遗留的问题

 

1. Σ=XXT好像并不是协方差矩阵?

用Matlab自带的cov() 函数检验,发现协方差矩阵应该等于(XTX)/N呢

2. “前k个”特征向量,是指将特征值按绝对值大小降序排列后,取相应的前k个特征向量吗?



附录:完整代码(含注释)

 

%PCA test: calculate Mean,X,Sigma,and itseigen decomposition

close all; clear all; clc;

 

%训练模块:~

%========================预处理:将训练集数据中心化========================%

 

training_set=[];             %创建一个空白数组,用于存放所有训练集图像

for i=1:40

    for j=1:5                     %只读取每个人的前五张图片作为训练图像

       a=imread(strcat('s',num2str(i),'\',num2str(j),'.bmp'));

       b=a(1:112*92);      %将以上数据转换为1×N的行向量存入bN=112×92=10304

                            %提取顺序是从上到下,从左到右

       b=double(b);        %强制数据类型转换,便于后面的运算操作

       training_set=[training_set;b];

       %每循环一次,就在原来的traing_set后面添加一行

       %traing_set是一个M×N矩阵,每一行代表一张图片。M=40×5=200, N=10304

    end

end

 

Mean=mean(training_set);   

%计算平均图片,得到一个1×N的行向量

 

for i=1:200

   X(i,:)=training_set(i,:)-Mean;

    %每个图片的数据都减去均值,实现训练集数据的均值归零(中心化)

    %减号两边的数据类型必须相同,原始数据的像素灰度值为整数,而平均值是浮点数,

    ...所以前面要转换。

    %XM×N矩阵,每一行保存的数据是:每个原始图片 -平均图片

end

 

figure;

%开个图形窗口

subplot(1,2,1),imshow(mat2gray(reshape(Mean,112,92)));title('Mean');  

%窗口中,左图显示200张训练集的平均脸

subplot(1,2,2),imshow(mat2gray(reshape(X(1,:),112,92)));title('S1P1-Mean');

%窗口中,右图显示第一个人的第一张图片(记为s1p1)减去平均脸后的效果。

 

 

 

%==================计算协方差矩阵及其前k个特征值、特征向量==================%

 

k=15;                       %暂时把维数选为15,即采用影响最大的15个特征

Sigma=X*X';                 %计算协方差矩阵M×M矩阵

[V,D]=eigs(Sigma,k);        %计算协方差矩阵的前k个特征值和特征向量

 

%矩阵Dk×k对角矩阵,对角元是Sigma的前k个特征值

%VM×k矩阵,每一列是一个特征向量,与D的每一列所含的那个特征值相互对应

 

 

 

%======================= 计算k个特征脸,并显示出来 ========================%

 

E=X'*V;                     %计算特征脸矩阵E,每一列是一张特征脸,共k

 

figure;

for i=1:15

subplot(3,5,i),imshow(mat2gray(reshape(E(:,i),112,92)));     

title(strcat('k=',num2str(i)));

%显示第1~15个主成分的特征脸

end

 

 

 

%======================== 利用特征脸,将训练集降维 ========================%

 

Train_E=training_set*E;    

%训练集数据降维,得到M×k矩阵(M=200,k=15),每行代表一张图片

%原来一张图片需要用N=112*92个数字表示,现在用k个数字来代替

 

 

 

%测试模块:~

%================= 读取测试集,并利用特征脸,将测试集降维 ==================%

 

testing_set=[];             %创建一个空白数组,用于存放所有测试集图像

for i=1:40

    for j=6:10             %读取每个人的后五张图片作为测试图像

       a=imread(strcat('s',num2str(i),'\',num2str(j),'.bmp'));

       b=a(1:112*92);      %将以上数据转换为1×N的行向量存入bN=112×92=10304

                            %提取顺序是从上到下,从左到右

       b=double(b);        %强制数据类型转换,便于后面的运算操作

       testing_set=[testing_set;b];

       %每循环一次,就在原来的testing_set后面添加一行

       %testing_set是一个M×N矩阵,每一行代表一张图片。M=40×5=200, N=10304

    end

end

 

Test_E=testing_set*E;

%测试集数据降维,得到M×k矩阵(M=200,k=15),每行代表一张图片

 

 

 

%=============== 比较降维后的训练集和样本集数据,得分类结果 ================%

 

correct=0;                  %初始化判断正确的人脸数

 

for i=1:200

    for j=1:200

       error(j)=norm(Test_E(i,:)-Train_E(j,:));

       %Test_E的第i行与Train_E的每一列求距离(即:相减,再取2-范数)

    end

   [errormin,I]=min(error);

    %算得距离最小的是第I

   

    true_class=ceil(i/5);   %实际上我知道当前这一行的数据是代表第几个人

   recog_class=ceil(I/5);  %而我让系统算出来是第几个人

   

    if true_class==recog_class

       correct=correct+1;  %如果系统判断正确,那么得一分~

    end

   

end

 

accuracy=correct/200        %输出正确率

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值