天天看点

基于BP神经网络人脸识别

Matlab代码(调用神经网络工具箱实现人脸识别)

a=input('请输入你需要提取的特征维数(仅限于8, 16,24, 32,48,64,80):');
for featureNumber =[a]%[8, 16,24, 32, 48, 64, 80]; % 特征维数,仅限于8, 16,24, 32,48,64,80
    %% 1.参数配置
    save featureNumber  featureNumber ;
    clear all; close all; warning off; format compact;%rng('default');
    load featureNumber ;
    disp('##################################################');
    disp(['----------------','featureNumber=',num2str(featureNumber ),'时','----------------']);
    %% 2.图片分块并计算每块的最大奇异值,并构成每张图片的特征向量
    num=1;
    %得出图片的路径,并自动读入每张图片
    dir = ['_1.bmp ';'_2.bmp ';'_3.bmp ';'_4.bmp '; '_5.bmp ';'_6.bmp '; '_7.bmp ';'_8.bmp ';'_9.bmp '; '_10.bmp'];
    for x=1:40
        %将数字转换成字符,便于把两个字符连接,组成图片的完整路径
        a = int2str(x);
        b = ['s'];
        d = [b a];
        for i=1:10
            %得到每张图片的文件名
            e = [d dir(i,1:7)];
            % 将图片转化成为灰度矩阵
            M = double(imread(e));
            %如果用户输入的是8,则执行下段代码,把数据处理得到8维的特征向量
            if (featureNumber == 8)
                for j=1:4
                    for k=1:2
                        %将图片的灰度矩阵划分成8块小矩阵
                        temp=M((j-1)*28+1:j*28,(k-1)*46+1:k*46);
                        %对每个小矩阵进行SVD变换
                        [u,temp1,v]=svd(temp);
                        %提取一个的SVD系数作为特征值
                        temp2=temp1(num,num);
                        %得到所有图片的特征矩阵
                        feature((x-1)*10+i,(j-1)*2+k)=temp2;
                    end
                end
            end
            %如果用户输入的是16,则执行下段代码,把数据处理得到16维的特征向量
            if (featureNumber == 16)
                for j=1:4
                    for k=1:4
                        %将图片的灰度矩阵划分成16块小矩阵
                        temp=M((j-1)*28+1:j*28,(k-1)*23+1:k*23);
                        %对每个小矩阵进行SVD变换
                        [u,temp1,v]=svd(temp);
                        %提取最大的SVD系数作为特征值
                        temp2=temp1(num,num);
                        %得到所有图片的特征矩阵
                        feature((x-1)*10+i,(j-1)*4+k)=temp2;
                    end
                end
            end
            %如果用户输入的是24,则执行下段代码,把数据处理得到16维的特征向量
            if (featureNumber == 24)
                for j=1:6
                    for k=1:4
                        %将图片的灰度矩阵划分成24块小矩阵
                        temp=M((j-1)*18+1:j*18,(k-1)*23+1:k*23);
                        %对每个小矩阵进行SVD变换
                        [u,temp1,v]=svd(temp);
                        %提取最大的SVD系数作为特征值
                        temp2=temp1(num,num);
                        %得到所有图片的特征矩阵
                        feature((x-1)*10+i,(j-1)*4+k)=temp2;
                    end
                end
            end
            %如果用户输入的是32,则执行下段代码,把数据处理得到32维的特征向量
            if (featureNumber == 32)
                for j=1:8
                    for k=1:4
                        %将图片的灰度矩阵划分成32块小矩阵
                        temp=M((j-1)*14+1:j*14,(k-1)*23+1:k*23);
                        %对每个小矩阵进行SVD变换
                        [u,temp1,v]=svd(temp);
                        %提取最大的SVD系数作为特征值
                        temp2=temp1(num,num);
                        %得到所有图片的特征矩阵
                        feature((x-1)*10+i,(j-1)*4+k)=temp2;
                    end
                end
            end
            %如果用户输入的是48,则执行下段代码,把数据处理得到48维的特征向量
            if (featureNumber == 48)
                for j=1:8
                    for k=1:6
                        %将图片的灰度矩阵划分成48块小矩阵
                        temp=M((j-1)*14+1:j*14,(k-1)*15+1:k*15);
                        %对每个小矩阵进行SVD变换
                        [u,temp1,v]=svd(temp);
                        %提取最大的SVD系数作为特征值
                        temp2=temp1(num,num);
                        %得到所有图片的特征矩阵
                        feature((x-1)*10+i,(j-1)*6+k)=temp2;
                    end
                end
            end
            %如果用户输入的是64,则执行下段代码,把数据处理得到64维的特征向量
            if (featureNumber == 64)
                for j=1:8
                    for k=1:8
                        %将图片的灰度矩阵划分成64块小矩阵
                        temp=M((j-1)*14+1:j*14,(k-1)*11+1:k*11);
                        %对每个小矩阵进行SVD变换
                        [u,temp1,v]=svd(temp);
                        %提取最大的SVD系数作为特征值
                        temp2=temp1(num,num);
                        %得到所有图片的特征矩阵
                        feature((x-1)*10+i,(j-1)*8+k)=temp2;
                    end
                end
            end
            %如果用户输入的是80,则执行下段代码,把数据处理得到80维的特征向量
            if (featureNumber == 80)
                for j=1:10
                    for k=1:8
                        temp=M((j-1)*11+1:j*11,(k-1)*11+1:k*11);%将图片的灰度矩阵划分成80块小矩阵
                        [u,temp1,v]=svd(temp);%对每个小矩阵进行SVD变换
                        temp2=temp1(num,num);%提取最大的SVD系数作为特征值
                        feature((x-1)*10+i,(j-1)*8+k)=temp2;%得到所有图片的特征矩阵
                    end
                end
            end
        end
    end
    tag=0;
    for x=1:40
        %将数字转换成字符,便于把两个字符连接,组成图片的完整路径
        a = int2str(x);
        b = ['s'];
        d = [b a];
        for i=1:10
            tag=tag+1;
            %得到每张图片的文件名
            e = [d dir(i,1:7)];
            %将图片转化成为灰度矩阵
            M = double(imread(e));
            picture(tag,:)=reshape(M,1,92*112);
        end
    end    
    %% 3.属于预处理(包括划分训练集和测试集, 数据归一化处理等)
    num_train=8;      %这里我们设置的每一类数据大小为10, 所以num_train的大小为1~10.
    feature=feature'; %进行矩阵倒置,因为该算法要求矩阵的行数比列数少
    num_test=10-num_train;
    for y=1:40        %构造训练集,一共有40个人,每人10张图片
        for n=1:num_train
            train_data(:,(y-1)*num_train + n) = feature(:,(y-1)*10 + n); %构造训练集
            train_picture((y-1)*num_train + n,:) = picture((y-1)*10 + n,:);
        end
        for z=1:num_test
            test_data(:,(y-1)*num_test+z)= feature(:,(y-1)*10 +num_train+z);%构造测试集
            test_picture((y-1)*num_test+z, :)= picture((y-1)*10 +num_train+z,:);
        end
    end
    for y=1:40
        for m=1:num_train
            t(y,(y-1)*num_train+m)=1;%构造训练集目标集
        end
    end
    max_train=max(train_data(:));
    min_train=min(train_data(:));
    pn = mat2gray(train_data,[min_train ,max_train]);%对训练集数据进行归一化处理
    pnewn = mat2gray(test_data,[min_train ,max_train]);%对测试集数据进行归一化处理   
    %% 4.训练BP神经网络
    %调用MATLAB神经网络工具箱,构建BP神经网络
    net = newff(minmax(pn),[110,40],{'tansig','purelin'},'trainrp');
    % 函数newff建立一个可训练的前馈网络。
    % (1) 函数功能:训练前馈网络的第一步是建立网络对象。
    %          输入参数说明:
    %          100表示: 输入隐含层神经元个数
    %          40表示: 输出层的个数(40个人的人脸,即40类)
    %          'tansig'表示: 输入层与隐含层之间的传递函数
    %          'purelin'表示:  隐含层与输出层之间的传递函数
    %          'trainrp'表示: BP网络训练函数(有弹回的BP算法,用于消除梯度模值对网络训练带来的影响,提高训练的速度)
    net.trainParam.goal=1e-5;%训练目标
    net.trainParam.epochs=10000;%训练次数
    net.trainParam.lr = 0.005;%学习速率
    [net,tr] = train(net,pn,t);  % 训练神经网络
    result_test=sim(net, pnewn);%测试模拟结果
    result_train=sim(net, pn);%训练模拟结果
    [~,I]=max(result_test);%C是得出的result_test中的每一列的最大值,I是最大值所在的行数
    [A,B]=max(result_train);%A是得出的result_train中的每一列的最大值,B是最大值所在的行数
    %%5识别效果
    II=I;BB=B;
    count_test=0;
    count_train=0;
    for f=1:40
        for g=1:num_test
        %计算在得出的结果中,被正确识别出来的测试集图片数目
            if(I(1,(f-1)*num_test+g)==f)
            count_test=count_test+1;
            end 
        end
        for h=1:num_train
        %计算在得出的结果中,被正确识别出来的训练集图片数目
            if(B(1,(f-1)*num_train+h)==f)
            count_train=count_train+1;
            end            
        end
    end
    fprintf('统计结束:\n正确识别的测试集数目为: %d\n',count_test);
    fprintf('正确识别的训练集数目为: %d\n',count_train);
    %计算出总识别率
    Total_reg=(count_test+count_train)/400;
    disp(['神经网络人脸识别率为:',num2str(Total_reg)])
    trainJ=cell(1,40);
    for k=1:40
        trainJ{1,k}= find(B==k);
        L(k)=length(trainJ{1,k});
    end
    Lmax=max(L);
    Imtrain=255*ones(40*112, Lmax*92);
    imtrain=mat2cell(Imtrain, 112*ones(1,40),92*ones(1,Lmax));
    for k=1:40
        trainJ{1,k}= find(B==k);
        tep=trainJ{1,k};
        L=length( trainJ{1,k});
        for jk=1:L
            tem=reshape(train_picture(tep(jk),:),112,92);
            imtrain{k,jk}=tem;
        end
    end
    Imtrain=cell2mat(imtrain);
    Lshow=10;%显示的人数
    showdata= Imtrain(1:Lshow*112, 1:Lmax*92);
    imshow( showdata,[]);
    title('聚类结果');
end
    %%6测试网络(选择图片识别,随机选择图像)
    r=randi(40);
    rr=randi(10);
    d=num2str(rr);
    d=['_',d,'.bmp'];
    r=int2str(r);
    d=[b r d];
    select_img=imread(d);  
    figure
    subplot(121); imshow(select_img);title('你选择的图片')
    M=double(select_img);
    num=1;%用最大的奇异值作特征值
    x=1;
    i=1;
    if (featureNumber == 8)
        for j=1:4
            for k=1:2
                %将图片的灰度矩阵划分成8块小矩阵
                temp=M((j-1)*28+1:j*28,(k-1)*46+1:k*46);
                %对每个小矩阵进行SVD变换
                [u,temp1,v]=svd(temp);
                %提取一个的SVD系数作为特征值
                temp2=temp1(num,num);
                %得到所有图片的特征矩阵
                f((x-1)*10+i,(j-1)*2+k)=temp2;
             end
        end
    end
    if (featureNumber == 16)
       for j=1:4
           for k=1:4
               %将图片的灰度矩阵划分成16块小矩阵
               temp=M((j-1)*28+1:j*28,(k-1)*23+1:k*23);
               %对每个小矩阵进行SVD变换
               [u,temp1,v]=svd(temp);
               %提取最大的SVD系数作为特征值
               temp2=temp1(num,num);
               %得到所有图片的特征矩阵
               f((x-1)*10+i,(j-1)*4+k)=temp2;
            end
        end
    end
    if (featureNumber == 24)
        for j=1:6
             for k=1:4
                 %将图片的灰度矩阵划分成24块小矩阵
                 temp=M((j-1)*18+1:j*18,(k-1)*23+1:k*23);
                 %对每个小矩阵进行SVD变换
                 [u,temp1,v]=svd(temp);
                 %提取最大的SVD系数作为特征值
                 temp2=temp1(num,num);
                 %得到所有图片的特征矩阵
                 f((x-1)*10+i,(j-1)*4+k)=temp2;
              end
         end
     end
     if (featureNumber == 32)
         for j=1:8
             for k=1:4
                 %将图片的灰度矩阵划分成32块小矩阵
                 temp=M((j-1)*14+1:j*14,(k-1)*23+1:k*23);
                 %对每个小矩阵进行SVD变换
                 [u,temp1,v]=svd(temp);
                 %提取最大的SVD系数作为特征值
                 temp2=temp1(num,num);
                 %得到所有图片的特征矩阵
                 f((x-1)*10+i,(j-1)*4+k)=temp2;
              end
          end
     end
     if (featureNumber == 48)
         for j=1:8
             for k=1:6
                 %将图片的灰度矩阵划分成48块小矩阵
                 temp=M((j-1)*14+1:j*14,(k-1)*15+1:k*15);
                 %对每个小矩阵进行SVD变换
                 [u,temp1,v]=svd(temp);
                 %提取最大的SVD系数作为特征值
                 temp2=temp1(num,num);
                 %得到所有图片的特征矩阵
                 f((x-1)*10+i,(j-1)*6+k)=temp2;
             end
          end
     end
      if (featureNumber == 64)
          for j=1:8
              for k=1:8
                  %将图片的灰度矩阵划分成64块小矩阵
                  temp=M((j-1)*14+1:j*14,(k-1)*11+1:k*11);
                  %对每个小矩阵进行SVD变换
                  [u,temp1,v]=svd(temp);
                  %提取最大的SVD系数作为特征值
                  temp2=temp1(num,num);
                  %得到所有图片的特征矩阵
                  f((x-1)*10+i,(j-1)*8+k)=temp2;
              end
          end
      end
      if (featureNumber == 80)
          for j=1:10
               for k=1:8
                   temp=M((j-1)*11+1:j*11,(k-1)*11+1:k*11); %将图片的灰度矩阵划分成80块小矩阵
                   [u,temp1,v]=svd(temp); %对每个小矩阵进行SVD变换
                   temp2=temp1(num,num);%提取最大的SVD系数作为特征值
                   f((x-1)*10+i,(j-1)*8+k)=temp2; %得到所有图片的特征矩阵
               end
           end
      end
      f=f';
      pnewn1 = mat2gray(f);
      result_test=sim(net,pnewn1);
      [C,I]=max(result_test);
      disp([ '该图像属于第',num2str(I),'个人的人脸图像']);
      subplot(122); imshow(strcat('s',num2str(I),'_', '1.bmp'));title('他/她的第一张图像')
           

训练过程

基于BP神经网络人脸识别

识别结果

基于BP神经网络人脸识别
基于BP神经网络人脸识别

需要orl人脸库图像的评论一下喔……

参考文章

[1]: https://blog.csdn.net/GaotYuan/article/details/79823170