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是最大值所在的行数
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
%选择图片识别,随机选择图像
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('他/她的第一张图像')
训练过程
识别结果
需要orl人脸库图像的评论一下喔。