源码 | 基于支持向量机 (SVM) 和稀疏表示理论 (SRC) 的人脸识别比较

这篇是本博客第二篇文章的续文,即关于SVM和SRC做人脸识别我所做的代码实现(Matlab)。虽然说目前绝大部分都是用深度学习来做人脸识别,而且效果一骑绝尘,但是某些特定条件下(比如小样本)传统方法依然是值得大家回顾与学习的。 至于理论部分,请见:  https://blog.csdn.net/weixin_43795395/article/details/88729251

所用到的Yale数据集,重新上传了百度云: 

链接: https://pan.baidu.com/s/1FBsuYheRwX4WTmjrE0cmTw 提取码: 1mxn 

Now! 

完整代码已上传至Github:https://github.com/maxee1900     走过路过不要忘了点个星星啊@!@


SVM算法代码

 

% Face recognition on yale data---SVM方法

% by Ma Xin. 2018.6.22

clear all

clc

close all

%% 读取人脸数据、降采样

yaleData = 'C:\Users\maxee\Desktop\matlab\yaleBExtData ';

dataDir = dir(yaleData);  %dir 列出指定路径下的所有子文件夹和子文件

for i = 3:40

  facefile = [yaleData,'\',dataDir(i).name];

  oneperson = dir ([facefile, '\*.pgm']);

  Asample = [];

  for j = 1:length(oneperson)-1

      image = imread([oneperson(j).folder,'\',oneperson(j).name]);

      downsample = image(1:4:192, 1:4:168);

      imagedouble = double(downsample);   %转化为double型

      faceshape = reshape(imagedouble,1,48*42);  %reshape按列顺序转换,不是随机的

      Asample = [Asample;faceshape];   %m行样本,n行维度

  end

 

   Allsample{i-2} = Asample;   %构成1*38的cell数组

  

end

%% 构造训练集合(p=7,13,20)

p = 13;

TrainData = [];

TestData = [];

TrainLabel = [];

TestLabel = [];

for i = 1:length(Allsample)

    % traindata and testdata for every person

    [m,~] = size(Allsample{i});

    randse = randperm(m);   %得到随机数列,因为不是所有的文件夹中都有64幅图像可用,故取m

    train_onep = Allsample{i}(randse(1:p),:);  

    test_onep = Allsample{i}(randse(p+1:m),:);

    trainlabel_onep = i * ones(p,1);

    testlabel_onep = i * ones(m-p,1);

   

    % sum to all traindata and testdata

    TrainData = [TrainData; train_onep];

    TestData = [TestData; test_onep];

    TrainLabel = [TrainLabel; trainlabel_onep];

    TestLabel = [TestLabel; testlabel_onep];

end

%% PCA降维至50,100,200维(原维度为2016)

trainsamples = TrainData';

testsamples = TestData';

[Pro_Matrix,Mean_Image]=my_pca(trainsamples,1000);

    %Pro_Matrix为投影矩阵

    train_project=Pro_Matrix'*trainsamples;

    test_project=Pro_Matrix'*testsamples;

TrainData = train_project';

TestData = test_project';

%% 归一化

%所有训练集和测试集

Data = [TrainData;TestData];

Label = [TrainLabel;TestLabel];

%样本顺序打乱形成新的数据

a = size(Data,1);

b = randperm(a);

RandData = Data(b,:);

RandLabel = Label(b);

Guiyi = mapminmax(RandData',-1,1);

NormData = Guiyi';

%% 构造最终的训练集和测试集,训练及测试

trainNum = size(TrainData,1);

DataNum = size(Data,1);

TrainSample = NormData(1:trainNum,:);

TrainSample_label = RandLabel(1:trainNum);

TestSample = NormData(trainNum+1:DataNum,:);

TestSample_label = RandLabel(trainNum+1:DataNum);

%训练模型,计算训练所用时间

t1 = clock;

model = svmtrain(TrainSample_label,TrainSample,'-s 0 -t 2 -c 50'); %选用高斯核函数

t2 = clock;

SVMtrainTime = etime(t2,t1);

%测试并计算平均每幅图片分类所用时间

t3 = clock;

[predicted_label, accuracy, decision_values] = svmpredict(TestSample_label,TestSample,model);

t4 = clock;

TestTime = etime(t4,t3);

t = TestTime / size(TestSample,1);

fprintf('模型训练时间为:%3.4fs\n',SVMtrainTime);

fprintf('平均每幅图片分类所用时间为:%3.4fs\n',t);


SRC算法代码

(说明:其中引用了其他作者的L1范数优化算法代码SolveHomotopy_CBM_std.m,因为篇幅较长本文中省略。)

% Face recognition on yale data---稀疏表示方法(SRC)

% by Ma Xin. 2018.6.22

clear all

clc

close all

%精度 测试时间 实验次数

Accu = zeros(1,10);   

Time = zeros(1,10);

for k = 1:10  

 

clearvars -except Accu Time k    %清除其他变量 

%% 读取人脸数据、降采样,形成数据集和标签集

yaleData = 'C:\Users\maxee\Desktop\matlab\yaleBExtData ';

dataDir = dir(yaleData);  %dir 列出指定路径下的所有子文件夹和子文件

label = [];

allsamples = [];

for i = 3:40

  facefile = [yaleData,'\',dataDir(i).name];

  oneperson = dir ([facefile, '\*.pgm']);

  Asample = [];

 

  for j = 1:length(oneperson)-1

      image = imread([oneperson(j).folder,'\',oneperson(j).name]);

      downsample = image(1:4:192, 1:4:168);

      imagedouble = double(downsample);   %转化为double型

      faceshape = reshape(imagedouble,48*42,1);  %reshape按列顺序转换,不是随机的

      Asample = [Asample,faceshape]; 

      allsamples = [allsamples,faceshape];  %所有数据样本:m列样本,n行维度

      label = [label,i-2];   %所有标签集

  end

 

   Allsample{i-2} = Asample;   %构成1*38的cell数组

end

%% 分出训练集和测试集 (p=7,13,20)

p = 13;

trainsamples = [];

testsamples = [];

trainlabels = [];

testlabels = [];

for i = 1:length(Allsample)

    m = size(Allsample{i},2);

    randse = randperm(m);

    train_one = Allsample{i}(:,randse(1:p));

    test_one = Allsample{i}(:,randse(p+1:m));

    trainlabel_one = i * ones(1,p);

    testlabel_one = i * ones(1,m-p);

   

    trainsamples = [trainsamples,train_one];

    testsamples = [testsamples,test_one];

    trainlabels = [trainlabels,trainlabel_one];

    testlabels = [testlabels,testlabel_one];

end

%% PCA降维至50,100,200

[Pro_Matrix,Mean_Image]=my_pca(trainsamples,100);

    %Pro_Matrix为投影矩阵

    train_project=Pro_Matrix'*trainsamples;

    test_project=Pro_Matrix'*testsamples;

   

%% 单位化

trainNorm = normc(train_project);

testNorm = normc(test_project);

%% 识别并计算准确率

testNum = size(testNorm,2);   %总测试数

trainNum = size(trainNorm,2);   %总训练数

labelpre = zeros(1,testNum);   %标签预测分配内存

classnum = length(Allsample);

 h = waitbar(0,'please wait...');   %进度条函数,数值在0~1

 

 for i = 1:testNum

    t1 = clock;

    xp = SolveHomotopy_CBM_std(trainNorm,testNorm(:,i),'lambda',0.01);

    %针对第i个测试样本,用Homotopy方法求优化解,稀疏表示优化算法之一,用到了L1和L2范数

    r = zeros(1, classnum);

   

    for j = 1:classnum

        %将xp中元素处理后归于xn.其中xp中与j类对应的元素保留,其他的为0

        xn = zeros(trainNum,1);                  

        index = (j==trainlabels);   %index为bool变量

        xn(index) = xp(index);   %index与xp中位置自动对齐

   

        r(j) = norm((testNorm(:,i) - trainNorm * xn));   %误差的2范数

    end

   

    [~,pos] = min(r);    %返回r中误差最小的位置

    labelpre(i) = pos;

    t2 = clock;

    testtime(i) = etime(t2,t1);

    per = i / testNum;

    waitbar(per,h,sprintf('第%d次实验:%2.0f%%',k,per*100));   %显示每个样本测试进度条   

 end

close(h);

Avtest_time = mean(testtime,2);

accuracy = sum(labelpre == testlabels) / testNum;

fprintf('第%d次实验识别率为:%5.2f%%\n\n',k,accuracy*100);

fprintf('第%d次实验平均每幅图片分类所用时间为:%6.4fs\n',k,Avtest_time);

%% 保存第K次实验精度与测试时间

Accu(k) = accuracy;   

Time(k) = Avtest_time;

end


my_pca.m代码


function [Pro_Matrix,Mean_Image]=my_pca(Train_SET,Eigen_NUM)

%输入:

%Train_SET:训练样本集,每列是一个样本,每行一类特征,Dim*Train_Num

%Eigen_NUM:投影维数

%输出:

%Pro_Matrix:投影矩阵

%Mean_Image:均值图像

[Dim,Train_Num]=size(Train_SET);

 Mean_Image=mean(Train_SET,2); %各行的均值 维度的均值

 Train_SET=bsxfun(@minus,Train_SET,Mean_Image);  %每一行的元素减去每一行的均值 

 R=Train_SET*Train_SET'/(Train_Num-1); %

   

 [eig_vec,eig_val]=eig(R);  %特征向量和特征值 

 eig_val=diag(eig_val);  % 取矩阵的对角线返回到向量

 [~,ind]=sort(eig_val,'descend'); 

%按降序排列 ~为排列好的向量 ind为其对应在元向量的索引

 W=eig_vec(:,ind);   %原特征向量的矩阵,重新按列排列

 Pro_Matrix=W(:,1:Eigen_NUM);   %取1:投影维数

 




写博不易,您的支持让知识之花绽放得更美丽 ~_~ 

  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值