基於PCA和SVM的人臉識別


程序中采用的數據集是ORL人臉庫,該人臉庫共有400副人臉圖像,40人,每人10幅,大小為112*92像素,同一個人的表情,姿勢有少許變化。

程序的流程主要分為三部分,數據的預處理(PCA降維和規格化),數據的訓練階段,數據的識別階段

數據的預處理的流程圖如下:

數據的訓練流程圖如下:


識別流程:


下面貼上一些matlab的實現代碼:

數據預處理主要是兩個函數,ReadFaces和scaling,第一個函數是將訓練圖像存成一個200*10304的矩陣,第二個是對數據進行規格化,具體代碼如下:

function [imgRow,imgCol,FaceContainer,faceLabel] = ReadFaces(nFacesPerson,nPerson,bTest)
%nFacesPersonn-----每個人需要讀入的樣本數,默認為5
%nPerson     ------需要讀入的人數,默認為全部四十個人
%bTest       ------bool型參數。默認為0,表示讀入樣本前五張;1:表示后五張


%輸出:  FaceContainer------向量化人臉容器,nPerson*10304的二維矩陣,每行對應一個人臉向量


if nargin==0    %默認值   
    nFacesPerson = 5;
    nPerson      = 40;
    bTest        = 0;
elseif nargin<3
    bTest        = 0;
end


img=imread('PCA_face/data/ORL/s1_1.bmp')  %為計算尺寸先讀一張
[imgRow,imgCol]=size(img);


FaceContainer = zeros(nFacesPerson*nPerson,imgRow*imgCol);
facelabel     = zeros(nFacesPerson*nPerson,1);


%讀入訓練數據
for i=1:nPerson     %不同的人
    i1=mod(i,10);
    i0=char(i/10);
    strPath='PCA_face/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:nFacesPerson      %每一個人的前五張
        strPath=tempStrPath;
        if bTest==0
            strPath=strcat(strPath,'0'+j);
        else
            strPath=strcat(strPath,num2str(5+j));
        end
        
        strPath = strcat(strPath,'.bmp');
        img=imread(strPath);
        
        %把讀入的圖像按列存儲為行向量放入向量化人臉容器FaceContainer的對應行中
        FaceContainer((i-1)*nFacesPerson+j,:)= img(:)';
        faceLabel((i-1)*nFacesPerson+j)      = i;
    end
end
%保存人臉樣本矩陣
save('PCA_face/Mat/FaceMat.mat','FaceContainer');



function [ SVFM, lowVec,upVec ] = scaling( VecFeaMat,bTest,lRealBVec,uRealBVec)
% Input:  VecFeaMat --- 需要scaling的 m*n 維數據矩陣,每行一個樣本特征向量,列數為維數
%         bTest ---  =1:說明是對於測試樣本進行scaling,此時必須提供 lRealBVec 和 uRealBVec
%                       的值,此二值應該是在對訓練樣本 scaling 時得到的
%                    =0:默認值,對訓練樣本進行 scaling
%         lRealBVec --- n維向量,對訓練樣本 scaling 時得到的各維的實際下限信息
%         uRealBVec --- n維向量,對訓練樣本 scaling 時得到的各維的實際上限信息
%
% output: SVFM --- VecFeaMat的 scaling 版本
%         upVec --- 各維特征的上限(只在對訓練樣本scaling時有意義,bTest = 0)
%         lowVec --- 各維特征的下限(只在對訓練樣本scaling時有意義,bTest = 0)
if nargin<2
    bTest=0;
end


lTargB=-1;
uTargB=1;


[m n] = size(VecFeaMat);


if   bTest
    if nargin<4
        error('to do scaling on test,param must 4');
    end
    
    if nargout>1
        error('when do scaling ,only one output is supported');
    end
    
    for iCol = 1:n
        if  lRealBVec(iCol)==uRealBVec(iCol)
            SVFM(:,iCol) = uRealBVec(iCol);
            SVFM(:,iCol) = 0;
        else
            SVFM(:,iCol) = lTargB  +  ( VecFeaMat(:,iCol) - lRealBVec(iCol) ) / ( uRealBVec(iCol) - lRealBVec(iCol) ) * ( uTargB - lTargB );
        end
    end
else                %bTest  = 0
    upVec = zeros(1,n);
    lowVec= zeros(1,n);
    
    for iCol = 1:n
        lowVec(iCol) = min( VecFeaMat(:,iCol) );
        upVec(iCol)  = max( VecFeaMat(:,iCol) );
        
        if lowVec(iCol) == upVec(iCol)
            SVFM(:,iCol) = upVec(iCol);
            SVFM(:,iCol) = 0;
        else
            SVFM(:,iCol) = lTargB  +  ( VecFeaMat(:,iCol) - lowVec(iCol) ) / ( upVec(iCol) - lowVec(iCol) ) * ( uTargB - lTargB );
        end
    end
end

end

訓練階段的函數是train,代碼如下:

function train()
%整個訓練過程包括讀入圖像,PCA降維以及多類SVM訓練,各個階段的處理結果分別保存至文件:
%   將PCA變換矩陣W保存至 PCA_face\Mat\PCA.mat
%   將scaling的各維上下界信息保存至 PCA_face\Mat\scaling.mat
%   將PCA降維並且scaling后的數據保存至 PCA_face\Mat\trainData.mat
%   將多類SVM的訓練信息保存至 PCA_face\Mat\multiSVMTrain.mat


global imgRow;
global imgCol;

global W
display('');
display('');
display('訓練開始.....');


nPerson = 40;
nFacesPerson = 5;
nSplPerClass=zeros(1,nPerson);
display('讀入人臉數據');
[ imgRow, imgCol, FaceContainer, faceLabel] = ReadFaces(nFacesPerson, nPerson);
save('PCA_face\Mat\FaceMat.mat','FaceContainer');
display('..................');


nFaces = size(FaceContainer, 1);%樣本人臉數目


display('PCA降維...');


[pcaFaces, W] = fastPCA(FaceContainer, 20);


%pcaFaces是200*20的矩陣,每一行代表一張主成分臉
%W是分離變換矩陣, 10304*20的矩陣


visualize_pc(W);
display('............');


X=pcaFaces;
[X,A0,B0] = scaling(X);
save('PCA_face\Mat\scaling.mat','A0','B0');


%保存scaling的數據至trainData.mat
TrainData = X;
trainLabel = faceLabel;
save('PCA_face\Mat\trainData.mat','TrainData','trainLabel');
display('.........保存scaling的數據至trainData.mat..........');


for iPerson = 1:nPerson
    nSplPerClass(iPerson) = sum((trainLabel == iPerson));
end


multiSVMStruct = multiSVMTrain (TrainData, nSplPerClass, nPerson, Inf, 1);
display('正在保存訓練結果.....');


save('PCA_face\Mat\multiSVMTrain.mat','multiSVMStruct');


display('訓練結束.................');

end

識別階段的函數是

function class = SVMClassify(TestFace, multiSVMStruct)

%class  ------識別出的類別

%TestFace------測試圖像轉換的行向量經過降維后的1*20的行向量,並經過規定化到-1~+1之間

%multiSVMStruct結構體數組,保存了兩兩分類的svm結構體信息
if nargin<2
    t = dir('PCA_face\Mat\multiSVMTrain.mat');
    if length(t) == 0
        error('沒有找到訓練結果');
    end
    load('PCA_face\Mat\multiSVMTrain.mat');
end


%nClass = multiSVMStruct.nClass;
nClass=40;
%CASVMStruct = multiSVMStruct.CASVMStruct;
CASVMStruct = multiSVMStruct;
%%%%%投票策略解決多類問題


m = size(TestFace, 1);
Voting = zeros(m,nClass);


for iIndex = 1:nClass-1
    for jIndex = iIndex+1:nClass
        classes = svmclassify(CASVMStruct{iIndex}{jIndex},TestFace);
        
        %voting
        
        Voting(:,iIndex) = Voting(:,iIndex) + (classes==1);
        Voting(:,jIndex) = Voting(:,jIndex) + (classes==0);
    end
end


%decision by voting
[vecMaxValue, class] = max(Voting, [ ] , 2);




end


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM