PCA 人脸降维

1、从文件中读取图像数据(一共40个人,每人5张图片,图片大小为112*92,格式为pgm,每个人的图像单独存放在一个文件夹中)

function [imgRow,imgCol,FaceContainer,faceLabel]=ReadFaces(nFacesPerPerson, nPerson, bTest)
% 读入ORL人脸库的指定数目的人脸前前五张(训练)
%
% 输入:nFacesPerPerson --- 每个人需要读入的样本数,默认值为 5
%       nPerson --- 需要读入的人数,默认为全部 40 个人
%       bTest --- bool型的参数。默认为0,表示读入训练样本(前5张);如果为1,表示读入测试样本(后5张)
%
% 输出:FaceContainer --- 向量化人脸容器,nPerson * 10304 的 2 维矩阵,每行对应一个人脸向量

if nargin==0 %default value
    nFacesPerPerson=5;%前5张用于训练
    nPerson=40;%要读入的人数(每人共10张,前5张用于训练)
    bTest = 0;
elseif nargin < 3
    bTest = 0;
end

img=imread('Data/ORL/S1/1.pgm');%为计算尺寸先读入一张
[imgRow,imgCol]=size(img);


FaceContainer = zeros(nFacesPerPerson*nPerson, imgRow*imgCol);
faceLabel = zeros(nFacesPerPerson*nPerson, 1);

% 读入训练数据
for i=1:nPerson
    i1=mod(i,10); % 个位
    i0=char(i/10);
    strPath='Data/ORL/S';
    if( i0~=0 )
        strPath=strcat(strPath,'0'+i0);
    end
    strPath=strcat(strPath,'0'+i1);
    strPath=strcat(strPath,'/');
    tempStrPath=strPath;
    for j=1:nFacesPerPerson
        strPath=tempStrPath;
        
        if bTest == 0 % 读入训练数据
            strPath = strcat(strPath, '0'+j);
        else
            strPath = strcat(strPath, num2str(5+j));
        end
        
        strPath=strcat(strPath,'.pgm');
        img=imread(strPath);
       
        %把读入的图像按列存储为行向量放入向量化人脸容器faceContainer的对应行中
        FaceContainer((i-1)*nFacesPerPerson+j, :) = img(:)';
        faceLabel((i-1)*nFacesPerPerson+j) = i;
    end % j
end % i

% 保存人脸样本矩阵
save('FaceMat.mat', 'FaceContainer')

  2.主函数中调用上面的ReadFaces函数和fastPCA函数

function main(k)
% ORL 人脸数据集的主成分分析
%
% 输入:k --- 降至 k 维

% 定义图像高、宽的全局变量 imgRow 和 imgCol,它们在 ReadFaces 中被赋值
global imgRow;
global imgCol;

% 读入每个人的前5副图像
nPerson=40;
nFacesPerPerson = 5;
display('读入人脸数据...');
[imgRow,imgCol,FaceContainer,faceLabel]=ReadFaces(nFacesPerPerson,nPerson);
display('..............................');


nFaces=size(FaceContainer,1);%样本(人脸)数目
display('PCA降维...');
% LowDimFaces是200*20的矩阵, 每一行代表一张主成分脸(共40人,每人5张),每个脸20个维特征
% W是分离变换矩阵, 10304*20 的矩阵
[LowDimFaces, W] = fastPCA(FaceContainer, 20); % 主成分分析PCA
visualize_pc(W);%显示主成分脸,详见第4步的图像显示
save('LowDimFaces.mat', 'LowDimFaces');
display('计算结束。');

  3、fastPCA算法

 1 function [pcaA V] = fastPCA( A, k )
 2 % 快速PCA
 3 %
 4 % 输入:A --- 样本矩阵,每行为一个样本
 5 %      k --- 降维至 k 维
 6 %
 7 % 输出:pcaA --- 降维后的 k 维样本特征向量组成的矩阵,每行一个样本,列数 k 为降维后的样本特征维数
 8 %      V --- 主成分向量
 9 
10 [r c] = size(A);
11 
12 % 样本均值
13 meanVec = mean(A);
14 
15 % 计算协方差矩阵的转置 covMatT
16 Z = (A-repmat(meanVec, r, 1));
17 covMatT = Z * Z';
18 
19 % 计算 covMatT 的前 k 个本征值和本征向量
20 [V D] = eigs(covMatT, k);
21 
22 % 得到协方差矩阵 (covMatT)' 的本征向量
23 V = Z' * V;
24 
25 % 本征向量归一化为单位本征向量
26 for i=1:k
27     V(:,i)=V(:,i)/norm(V(:,i));
28 end
29 
30 % 线性变换(投影)降维至 k 维
31 pcaA = Z * V;
32 
33 % 保存变换矩阵 V 和变换原点 meanVec
34 save('PCA.mat', 'V', 'meanVec');

4、fastPCA函数的输出主分量阵W,是一个10340*20的矩阵,每列是一个10340维的主分量(样本协方差矩阵的本征向量),用112*92的分辨率来显示,

visualize_pc()代码如下
function visualize_pc(E)
% 显示主成分分量(主成分脸,即变换空间中的基向量)
%
% 输入:E --- 矩阵,每一列是一个主成分分量


[size1 size2] = size(E);
global imgRow;
global imgCol;
row = imgRow;
col = imgCol;

if size2 ~= 20
   error('只用于显示 20 个主成分');
end;

figure
img = zeros(row, col);
for ii = 1:20
    img(:) = E(:, ii);
    subplot(4, 5, ii);
    imshow(img, []);
end

 

 

5、补充:基于主分量的人脸重建

  

 1 function [ xApprox ] = approx( x, k )
 2 % 用 k 个主成分分量来近似(重建)样本 x
 3 %
 4 % 输入:x --- 原特征空间中的样本,被近似的对象
 5 %       k --- 近似(重建)使用的主分量数目
 6 %
 7 % 输出:xApprox --- 样本的近似(重建)
 8 
 9 % 读入 PCA 变换矩阵 V 和 平均脸 meanVec
10 load Mat/PCA.mat
11 
12 nLen = length(x);
13 
14 xApprox = meanVec;
15 
16 for ii = 1:k
17     xApprox=xApprox+((x-meanVec)*V(:,ii))*V(:,ii)';
18 end
 1 function displayImage(v,row,col)
 2 % 向量 v 为一幅图像按列存储得到的行向量,函数 displayImage(...) v 转化成原始的 row * col 图像,并显示之
 3 %
 4 % 输入:v --- 一幅图像按列存储得到的行向量
 5 %      row --- 原始图像的行数
 6 %      col --- 原始图像的列数
 7 
 8 [m n] = size(v);
 9 
10 
11 if m ~= 1
12    error('v必须为行向量');
13 end;
14 if  row*col ~= n
15    error('图像尺寸与输入向量 v 的维数不符');
16 end;
17 
18 % 原始图像I
19 I=zeros(row,col);
20 I(:)=v(:);
21 
22 
23 figure;
24 imagesc(I);
25 colormap(gray);
26 axis image;

 

posted @ 2016-12-19 16:31  白菜hxj  阅读(5911)  评论(1编辑  收藏  举报