基于PCA的人脸识别01 - 基本原理; Matlab使用入门; 训练集数据预处理

本文介绍主成分分析法(PCA)的基本原理及应用,利用PCA去除图像数据中的冗余信息,提高处理效率。通过MATLAB实现图像数据的均值归零、协方差矩阵计算等步骤。

墨迹了好一阵不知道从哪下手,终于硬着头皮开始折腾了。打算先借鉴别人做过的~ 对照着代码一点一点抠:

http://blog.csdn.net/hesays/article/details/39498375


--------------------------------- 2015/03/26 ---------------------------------

PCA的基本原理


前几天试着研究了一下主成分分析法(PCA)的原理,离理解透彻还差很远。之前学过的线性代数,由于用得少,基本上还给老师了。有很多基本概念都还不清楚,比如矩阵的特征向量和特征值,特征值分解,基,等等等等。CSDN上有很多大神的解释,看得似懂非懂,像本身不会英语还去查英英词典,对一个问题的解释又会牵扯出更多的问题,实在是看不到头。暂时允许自己不求甚解一次,只阐述主要的部分,在以后的研究中如果有了更深的理解再重新作整理和总结。


1. 为什么需要用到PCA

图像本身的数据量大,导致处理过程的计算量大。但数据之间存在一定的相关性,也就是说这些信息中有大量的冗余。PCA的目的就在于检测并试图去除这种相关性,提取出数据的主要成分,从而降低冗余,提高信息处理的效率。


2. 实现步骤:

使用ORL人脸数据库进行实验,数据库共有400幅图像,40个人每人10幅,图像尺寸为112x92。人为地将数据库分为训练集和测试集:将每个人的前5幅图像作为训练集,用于学习每个人的特征;后5幅图像作为测试集,作为系统的输入,逐个判断其类别,并计算识别率。

①将训练集原始数据中心化(即:均值归零)

②计算协方差矩阵、以及它的特征值和对应的特征向量

③选取最大的k个特征值及其对应特征向量,组成一组新的基

④将测试集图像对这组新的基投影,得到降维后的新特征,即所谓的特征脸

⑤采用恰当的分类准则(例如最小距离准则)判定输入人脸是谁  [待定]


3. 理解难点:为什么通过协方差矩阵的特征值分解,就能得到数据的主成分? [待补充]


--------------------------------- 2015/03/28 ---------------------------------

MATLAB使用入门


1. 前面的内容看起来太高大上了。。打开Matlab还是啥也不会,摔。。先从最简单的入手吧。你都想不到有多简单:我来加载一张图片

ORL人脸数据库的40个人各有10张图片,分别放在s1,s2,s3,...,s40这样的子文件夹里。如果当前工作路径是s1文件夹,用 imread() 函数读取图片的时候,括号里的内容只需填写文件名+后缀。如果当前工作路径不是s1,那么使用 imread() 时应在括号里给出文件完整路径。

前面所说参考的那篇文章里,作者将400张图片重新命名,比如第16个人的第9张图片命名为 016009,这样文件名中就包含了“该图片属于第几个样本”的信息,感觉对测试时计算识别率可能有用,不知道有没有这个必要,[待定]


2. 下面来计算s1这个文件夹里10张图片的平均值



第一次出错之后发现,想要用某个变量 i 来控制图像自动依次读取,就必须使用 strcat() 这个函数。num2str(i) ,即 number to string,的意思是将循环变量 i 这个数字转变为字符串。接下来再由 strcat() 函数将字符串 i 和后面的‘.bmp’拼接起来,共同组成文件名。

上面这一小片代码的解释:

 samples=[];                                          %Create an EMPTY vector.用于存放10张图片的灰度值信息,每一行代表一张图片

 for i=1:10
       a=imread(strcat(num2str(i),'.bmp'));           %读取第i张图片,存入a
       b=a(1:112*92);                                 %将a转换为一维数组(即行向量),存入b
       b=double(b);                                   %转换数据类型为double
       samples=[samples;b];                           %每循环一次,就在原来的sample后面添加一行
 end
 
 samplemean=mean(samples);                            %mean()函数,求输入矩阵的每一列的均值,并返回一个行向量samplemean
 figure,imshow(mat2gray(reshape(samplemean,112,92))); %将samplemean这个行向量reshape为112x92的数组,mat2gray=matrix to grayscale image


转换数据类型为double的意义暂不明确,试过删掉这一行,好像并不影响结果。

Matlab的帮助系统很好用,不懂的函数就去Product help里搜,会有解释和举例,很清楚~


3. 下面来计算所有训练样本(放在40个文件夹中的200张图片)的平均值,并对训练集数据进行均值归零

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的行向量存入b,N=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;
    %每个图片的数据都减去均值,实现训练集数据的均值归零(中心化)
    %减号两边的数据类型必须相同,原始数据的像素灰度值为整数,而平均值是浮点数,所以前面要转换。
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)减去平均脸后的效果。


这一步曾经因为没有把 b 的数据类型转换为double而报错了:因为对原始图片数据和平均值数据进行了减法操作。减号两边的数据类型必须相同,原始数据的像素灰度值为整数,而平均值是浮点数。所以前面的代码中必须加上数据类型转换,后面才能相减。


显示的结果如下图:



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值