当前位置: 首页 > news >正文

基于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

转载于:https://www.cnblogs.com/anyuan9/p/6171580.html

相关文章:

  • markdonw 一个模版
  • android超快模拟器Ggenymotion的安装和配置
  • NSUserDefaults设置bool值重启后bool只设置丢失问题
  • 01_Android应用开发环境_03_开发环境搭建及简单Android程序
  • 信息学奥赛辅导经验谈 问题教学法中的学生思维能力培养
  • HTTP 404 - 未找到文件 怎么样解决
  • (转)chrome浏览器收藏夹(书签)的导出与导入
  • JS获得当月的天数和得到当月最后一天的日期
  • void (*f(int, void (*)(int)))(int) 函数解析
  • 我爱淘冲刺阶段站立会议每天任务4
  • jetty运行maven程序(修改及时生效,不需要重启jetty程序)
  • 转:python的命令行输入参数
  • 微一微博的应用项目源码
  • DOM操作
  • Python:利用内建函数将字符串转化为整数
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • Consul Config 使用Git做版本控制的实现
  • Java 内存分配及垃圾回收机制初探
  • JS+CSS实现数字滚动
  • LintCode 31. partitionArray 数组划分
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Node + FFmpeg 实现Canvas动画导出视频
  • Nodejs和JavaWeb协助开发
  • Spark学习笔记之相关记录
  • uni-app项目数字滚动
  • VUE es6技巧写法(持续更新中~~~)
  • 关于 Cirru Editor 存储格式
  • 可能是历史上最全的CC0版权可以免费商用的图片网站
  • 手写一个CommonJS打包工具(一)
  • 新手搭建网站的主要流程
  • 最近的计划
  • 阿里云重庆大学大数据训练营落地分享
  • ​Python 3 新特性:类型注解
  • ​Spring Boot 分片上传文件
  • #AngularJS#$sce.trustAsResourceUrl
  • (4)Elastix图像配准:3D图像
  • (windows2012共享文件夹和防火墙设置
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (汇总)os模块以及shutil模块对文件的操作
  • (蓝桥杯每日一题)love
  • (全注解开发)学习Spring-MVC的第三天
  • (四)linux文件内容查看
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (译) 函数式 JS #1:简介
  • (转)linux 命令大全
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET6 命令行启动及发布单个Exe文件
  • .net操作Excel出错解决
  • .NET开源快速、强大、免费的电子表格组件
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • [ C++ ] STL---string类的模拟实现
  • []C/C++读取串口接收到的数据程序