PCA 人脸降维

摘要:
1.从文件函数[imgRow,imgCol,FaceContainer,faceLabel]=ReadFaces%读取ORL人脸数据库(训练)中指定数字的前五个人脸%%Input:nFacesPersPerson-每个人需要读取的样本数。默认值为5%Person-要阅读的人数。默认值为所有40人%bTest-book类型参数。

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

PCA 人脸降维第1张

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;

免责声明:文章转载自《PCA 人脸降维》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇【转】TCP/UDP简易通信框架源码,支持轻松管理多个TCP服务端(客户端)、UDP客户端[转]Jsoup(一)Jsoup详解(官方)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

高斯消元讲解 &amp;amp;&amp;amp; 洛谷P3389 【模板】高斯消元法 题解

前言:回去刷数论的题,发现自己的高斯消元是0分。。。。。。很可能是当年交上去了没看结果就直接过了。。。。。。回来博客园搜自己之前对高斯消元的讲解想看看,没看到。只能从头过了一遍,顺便补上之前的锅。 高斯消元: 什么是高斯消元: 线性代数规划中的一个算法,可用来为线性方程组求解——度娘 在现阶段的学习中,高斯消元常被应用于求多项式的解: 形如 x+3y+2...

14-高效求最长公共子序列(二维数组存不下)

/* See LCS again时间限制:1000 ms | 内存限制:65535 KB难度:3描述There are A, B two sequences, the number of elements in the sequence is n、m;Each element in the sequence are different and less t...

VTK 空间几何变换(Transform),平移、旋转和缩放

先看下面的模型,这是一个Cow的三维模型, 在使用中,你是否会有下面的操作? 1.将Cow移动到某个位置——平移 2.转动到Cow背面——旋转 3.改变它大小——缩放 等等 可能你会说,这还不简单,通过操作相机就好了。然而并不是这样,操作相机,只使得相机的空间位置发生了变化,对三维物体并没有改变,要想改变模型,就需要对模形本身做空间变换。 空间变换的基础...

有向图邻接矩阵的幂敛指数与周期【图论】

Description 定义有向图邻接矩阵A的周期为最小的d,使得存在正整数k,对于任意n>=k,都有(A^n=A^{n+d})最小的k称为A的幂敛指数。 现给出一个n个点,m条边有向图,求它的邻接矩阵的周期对10^9+7取模的结果。n<=100000,m<=200000 对于n<=200,m<=3000的数据,你还需要求出它...

「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手试试做实验,不管成功与否,都会记录下来---小小的进步或是搞不定的问题,希望能够抛砖引玉。 【Arduino】108种传感器模块系列实验(资料+代...

ELM学习(一)

what?: 极限学习机(extreme learning machine)ELM是一种简单易用、有效的单隐层前馈神经网络SLFNs学习算法。2004年由南洋理工大学黄广斌副教授提出。传统的神经网络学习算法(如BP算法)需要人为设置大量的网络训练参数,并且很容易产生局部最优解。极限学习机只需要设置网络的隐层节点个数,在算法执行过程中不需要调整网络的输入权...