(11)MATLAB PCA+SVM 人脸识别

 PCA主要代码

function [pcaA V] = fastPCA( A, k )
% 快速PCA
%
% 输入:A --- 样本矩阵,每行为一个样本
%      k --- 降维至 k 维
%
% 输出:pcaA --- 降维后的 k 维样本特征向量组成的矩阵,每行一个样本,列数 k 为降维后的样本特征维数
%      V --- 主成分向量

[r c] = size(A);

% 样本均值
meanVec = mean(A);

% 计算协方差矩阵的转置 covMatT
Z = (A-repmat(meanVec, r, 1));
covMatT = Z * Z';

% 计算 covMatT 的前 k 个本征值和本征向量
[V D] = eigs(covMatT, k);

% 得到协方差矩阵 (covMatT)' 的本征向量
V = Z' * V;

% 本征向量归一化为单位本征向量
for i=1:k
    V(:,i)=V(:,i)/norm(V(:,i));
end

% 线性变换(投影)降维至 k 维
pcaA = Z * V;

% 保存变换矩阵 V 和变换原点 meanVec
save('Mat/PCA.mat', 'V', 'meanVec');

function [ xApprox ] = approx( x, k )
% 用 k 个主成分分量来近似(重建)样本 x
%
% 输入:x --- 原特征空间中的样本,被近似的对象
%       k --- 近似(重建)使用的主分量数目
%
% 输出:xApprox --- 样本的近似(重建)

% 读入 PCA 变换矩阵 V
load Mat/PCA.mat

nLen = length(x);

xApprox=zeros(1, nLen);

for ii = 1:k
    xApprox=xApprox+(x*V(:,ii))*V(:,ii)';
end
function visualize_pc(E)
% 显示主成分分量(主成分脸,即变换空间中的基向量)
%
% 输入:E --- 矩阵,每一列是一个主成分分量


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

if size2 ~= 20
   error('Can only display 20 principle components');
end;

c1 = zeros(row,col*5);
c2 = c1;
c3 = c1;
c4 = c1;
c1(:) = E(:,1:5);
c2(:) = E(:,6:10);
c3(:) = E(:,11:15);
c4(:) = E(:,16:20);
size(c1)

composite=zeros(row*4,col*5);
composite(:)=[c1;c2;c3;c4];

figure;
colormap(gray);
imagesc(composite);   
axis image;
m=min(min(composite));
M =max(max(composite));
imwrite(uint8((composite-m)*(255/(M-m))),'composite.tiff');

SVM主要代码

function multiSVMStruct = multiSVMTrain(TrainData, nSampPerClass, nClass, C, gamma)
%function multiSVMStruct = multiSVMTrain(TrainData, nSampPerClass, nClass, C, gamma)
% 采用1对1投票策略将 SVM 推广至多类问题的训练过程,将多类SVM训练结果保存至multiSVMStruct中
%
% 输入:--TrainData:每行是一个样本人脸
%     --nClass:人数,即类别数
%     --nSampPerClass:nClass*1维的向量,记录每类的样本数目,如 nSampPerClass(iClass)
%     给出了第iClass类的样本数目
%     --C:错误代价系数,默认为 Inf
%     --gamma:径向基核函数的参数 gamma,默认值为1
%
% 输出:--multiSVMStruct:一个包含多类SVM训练结果的结构体

% 默认参数
if nargin < 4
    C = Inf;
    gamma = 1;
elseif nargin < 5
    gamma = 1;
end



%开始训练,需要计算每两类间的分类超平面,共(nClass-1)*nClass/2个
for ii=1:(nClass-1)
    for jj=(ii+1):nClass
        clear X;
        clear Y;
        startPosII = sum( nSampPerClass(1:ii-1) ) + 1;
        endPosII = startPosII + nSampPerClass(ii) - 1;
        X(1:nSampPerClass(ii), :) = TrainData(startPosII:endPosII, :);
            
        startPosJJ = sum( nSampPerClass(1:jj-1) ) + 1;
        endPosJJ = startPosJJ + nSampPerClass(jj) - 1;
        X(nSampPerClass(ii)+1:nSampPerClass(ii)+nSampPerClass(jj), :) = TrainData(startPosJJ:endPosJJ, :);
        
        
        % 设定两两分类时的类标签
        Y = ones(nSampPerClass(ii) + nSampPerClass(jj), 1);
        Y(nSampPerClass(ii)+1:nSampPerClass(ii)+nSampPerClass(jj)) = 0;
        
        % 第ii个人和第jj个人两两分类时的分类器结构信息
        CASVMStruct{ii}{jj}= svmtrain( X, Y, 'Kernel_Function', @(X,Y) kfun_rbf(X,Y,gamma), 'boxconstraint', C );
     end
end

% 已学得的分类结果
multiSVMStruct.nClass = nClass;
multiSVMStruct.CASVMStruct = CASVMStruct;

% 保存参数
save('Mat/params.mat', 'C', 'gamma');

function class = multiSVMClassify(TestFace, multiSVMStruct)
% 采用1对1投票策略将 SVM 推广至多类问题的分类过程
% 输入:--TestFace:测试样本集。m*n 的2维矩阵,每行一个测试样本
%     --multiSVMStruct:多类SVM的训练结果,由函数 multiSVMTrain 返回,默认是从Mat/multiSVMTrain.mat文件中读取
%
% 输出:--class: m*1 列向量,对应 TestFace 的类标签


% 读入训练结果
if nargin < 2
    t = dir('Mat/multiSVMTrain.mat');
    if length(t) == 0
        error('没有找到训练结果文件,请在分类以前首先进行训练!');
    end
    load('Mat/multiSVMTrain.mat');
end

nClass = multiSVMStruct.nClass; % 读入类别数
CASVMStruct = multiSVMStruct.CASVMStruct; % 读入两两类之间的分类器信息



%%%%%%%%%%%%%%%%%%%%%%%% 投票策略解决多类问题 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
m = size(TestFace, 1);
Voting = zeros(m, nClass); % m个测试样本,每个样本nPerson 个类别的投票箱

for iIndex = 1:nClass-1
    for jIndex = iIndex+1:nClass
        classes = svmclassify(CASVMStruct{iIndex}{jIndex}, TestFace);

        % 投票
        Voting(:, iIndex) = Voting(:, iIndex) + (classes == 1);
        Voting(:, jIndex) = Voting(:, jIndex) + (classes == 0);
                
    end % for jClass
end % for iClass



% final decision by voting result
[vecMaxVal, class] = max( Voting, [], 2 );
%display(sprintf('TestFace对应的类别是:%d',class));



 训练过程主要代码

function train(C, gamma)
% 整个训练过程,包括读入图像,PCA降维以及多类 SVM 训练,各个阶段的处理结果分别保存至文件:
%   将 PCA 变换矩阵 W 保存至 Mat/PCA.mat
%   将 scaling 的各维上、下界信息保存至 Mat/scaling.mat
%   将 PCA 降维并且 scaling 后的数据保存至 Mat/trainData.mat
%   将多类 SVM 的训练信息保存至 Mat/multiSVMTrain.mat


global imgRow;
global imgCol;
global SVM;


display(' ');
display(' ');
display('训练开始...');

nPerson=40;
nFacesPerPerson = 5;
display('读入人脸数据...');
[imgRow,imgCol,FaceContainer,faceLabel]=ReadFaces(nFacesPerPerson,nPerson);
display('..............................');


nFaces=size(FaceContainer,1);%样本(人脸)数目

display('PCA降维...');
[pcaFaces, W] = fastPCA(FaceContainer, 20); % 主成分分析PCA
% pcaFaces是200*20的矩阵, 每一行代表一张主成分脸(共40人,每人5张),每个脸20个维特征
% W是分离变换矩阵, 10304*20 的矩阵
visualize_pc(W);%显示主成分脸
display('..............................');

X = pcaFaces;

display('归一化开始...');
display('.........');
[X,A0,B0] = scaling(X);
save('Mat/scaling.mat', 'A0', 'B0');
% 保存 scaling 后的训练数据至 trainData.mat
TrainData = X;
trainLabel = faceLabel;
save('Mat/trainData.mat', 'TrainData', 'trainLabel');
display('归一化完成...');

display('训练分类器开始,这个过程可能会花上几分钟.........................');
if(get(SVM,'value')==1)
    for iPerson = 1:nPerson
        nSplPerClass(iPerson) = sum( (trainLabel == iPerson) );
    end

    multiSVMStruct = multiSVMTrain(TrainData, nSplPerClass, nPerson, C, gamma);
    display('正在保存SVM训练结果...');
    save('Mat/multiSVMTrain.mat', 'multiSVMStruct');
else
display('..............................');
display('训练完成。');







测试效率主要代码

function test()
% 测试对于整个测试集的识别率
%
% 输出:accuracy --- 对于测试集合的识别率

global SVM;
global Adaboost;

display(' ');
display(' ');
display('测试开始...');

nFacesPerPerson = 5;
nPerson = 40;
bTest = 1;
% 读入测试集合
display('读入测试集合...');
[imgRow,imgCol,TestFace,testLabel] = ReadFaces(nFacesPerPerson, nPerson, bTest);
display('..............................');

% 读入相关训练结果
display('载入训练参数...');

    load('Mat/PCA.mat');
    load('Mat/scaling.mat');
    load('Mat/trainData.mat');
    load('Mat/multiSVMTrain.mat');
    display('..............................');

    % PCA降维
    display('PCA降维处理...');
    [m n] = size(TestFace);
    TestFace = (TestFace-repmat(meanVec, m, 1))*V; % 经过pca变换降维
    TestFace = scaling(TestFace,1,A0,B0);
    display('..............................');

    % 多类 SVM 分类
    display('测试集识别中...');
    classes = multiSVMClassify(TestFace);
    display('..............................');

    % 计算识别率
    nError = sum(classes ~= testLabel);
    accuracy = 1 - nError/length(testLabel);
    display(['PCA+SVM对于测试集200个人脸样本的识别率为', num2str(accuracy*100), '%']);


 




识别主要代码

function nClass = classify(newFacePath)
% 整个分类(识别)过程
global SVM;
global Adaboost;

display(' ');
display(' ');
display('识别开始...');

% 读入相关训练结果
display('载入训练参数...');

    load('Mat/PCA.mat');
    load('Mat/scaling.mat');
    load('Mat/trainData.mat');
    load('Mat/multiSVMTrain.mat');
    
    display('..............................');

    xNewFace = ReadAFace(newFacePath); % 读入一个测试样本
    xNewFace = double(xNewFace);
    xNewFace = (xNewFace-meanVec)*V;% 经过pca变换降维
    xNewFace = scaling(xNewFace,1,A0,B0);


    display('身份识别中...');
    nClass = multiSVMClassify(xNewFace);
    display('..............................');
    display(['身份识别结束,类别为:' num2str(nClass), '。']);




  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值