zoukankan      html  css  js  c++  java
  • 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;
  • 相关阅读:
    FileStreamResult 下载或导出文件
    .net core post自带的json序列化转换出错 post参数为null
    .net Core CodeFirst
    获得IP地址
    vue cli 3 以上添加Less支持
    npm淘宝镜像
    会话状态在此上下文中不可用HttpModule中无法访问Session原因
    Chrome谷歌浏览器中js代码Array.sort排序的bug乱序解决办法
    JS匿名函数递归实现阶乘
    JS URL解析
  • 原文地址:https://www.cnblogs.com/hxjbc/p/6197986.html
Copyright © 2011-2022 走看看