基于BP神经网络的人脸朝向识别

一、数字图像处理
1.1 问题假设

  • 所给的全部人脸图像都未出现损坏等问题;
  • 人脸的朝向仅分为5类:左、中左、中间、中右、右,其他朝向不予考虑;
  • 对于题目中所给的人脸图像,不考虑人脸的复杂表情问题;

1.2 基于边缘检测Sobel算子的人脸特征向量提取

人脸识别的第一步便是人脸特征的提取,即如何把人脸图像转换成数字特征值。目前人脸特征提取的方法有很多,如主元分析法、Fisher线性判别法、小波分析法等。通过特征向量提取,作为神经网络的输入。通过对人脸朝向图片分析,当人脸朝向不同时,眼睛在图像中的位置会有明显的差别。因此,只需要将人眼位置信息的特征向量提取出来即可。主要方法是先进行检测图像边界,再利用得到的边界信息进行特征提取。由于Sobel算子对灰度渐变的图像处理效果较好,不仅能够检测到边缘点,而且能进一步抑制噪声的影响。因此本采用Sobel算测提取人脸边界。

在MATLAB工具箱中可采用函数edge(img,‘Sobel’)进行边缘检测,接着将图像划分成6行8列,人眼的位置信息可以用第2行的8个子矩阵来描述,经过分析人脸朝向与8个子矩阵中的值为1的像素点个数有直接关系。只要分别统计出第2行的8个子矩阵中的值为“1”的像素点即可。采用Sobel算法提取边界如下图所示:
在这里插入图片描述
二、BP神经网络
2.1 BP神经网络模型

BP神经网络是一种多层前向网络,由输入层、输出层、隐含层(可以是一层或多层)构成,一种典型的三层BP神经网络模型如图3所示。反向传播算法的主要思想是把学习过程分为2个阶段:第1阶段(正向传播过程),输入信息从输入层开始逐层计算个单元的实际输出值,每一层神经元的状态只对下一层神经元的状态产生影响。第2阶段(反向传输过程),若在输出层未能够得到期望的输出值,则逐层递归计算实际输出与期望输出之间的差值,根据此误差修正前层权值使误差信号趋向最小。它通过连续不断地在相对于误差函数斜率下降的方向上计算网络权值和偏差变化而逐渐逼近目标。每次权值和误差的变化都与网络误差的影响成正比。

在这里插入图片描述
2.2 代码展示

%BP神经网络训练
clc;
images=[ ];
M_train=8;%表示人脸
N_train=5;%表示方向
sample=[];
pixel_value=[];
sample_number=0;
k=0;
for j=1:N_train
for i=1:M_train
str=strcat('Images\',num2str(i),'_',num2str(j),'.bmp'); %读取图像,连接字符串形成图像的文件名。
img= imread(str);
[rows cols]= size(img);%获得图像的行和列值。
img_edge=edge(img,'Sobel');
k=k+1;
subplot(M_train,N_train,k)
imshow(img_edge)%显示灰度图
%由于在分割图片中我们可以看到这个人脸的眼睛部分也就是位于分割后的第二行中,位置变化比较大,而且眼睛边缘检测效果很好
sub_rows=floor(rows/6);%最接近的最小整数,分成6行
sub_cols=floor(cols/8);%最接近的最小整数,分成8列
sample_num=M_train*N_train;%5个是第一幅人脸的5个角度
sample_number=sample_number+1;
for subblock_i=1:8 %因为这还在i,j的循环中,所以不可以用i
block_num=subblock_i;
pixel_value(sample_number,block_num)=0;
for ii=sub_rows:(2*sub_rows)
for jj=(subblock_i-1)*sub_cols+1:subblock_i*sub_cols
pixel_value(sample_number,block_num)=pixel_value(sample_number,block_num)+img_edge(ii,jj);
end
end
end
end
end
%将特征值转换为小于1的值
max_pixel_value=max(pixel_value);
max_pixel_value_1=max(max_pixel_value);
for i=1:3
mid_value=10^i;
if(((max_pixel_value_1/mid_value)>1)&&((max_pixel_value_1/mid_value)<10))
multiple_num=1/mid_value;
pixel_value=pixel_value*multiple_num;
break;
end
end
%T 为目标矢量
t=zeros(1,sample_number);
%因为有五类,所以至少用3个数表示,5介于22次方和23次方之间
for i=1:sample_number
% if((mod(i,5)==1)||(mod(i,5)==4)||(mod(i,5)==0))
if(i<=M_train)
t(1,i)=1;
end
if(i>M_train&&i<=2*M_train)
t(1,i)=2;
end
if(i>2*M_train&&i<=3*M_train)
t(1,i)=3;
end
if(i>3*M_train&&i<=4*M_train)
t(1,i)=4;
end
if(i>4*M_train&&i<=5*M_train)
t(1,i)=5;
end
end
% NEWFF——生成一个新的前向神经网络
% TRAIN——对 BP 神经网络进行训练
% SIM——对 BP 神经网络进行仿真
%  定义训练样本
% P 为输入矢量
P=pixel_value'
% T 为目标矢量
T=t
size(P)
size(T)
% size(P)
% size(T)
%  创建一个新的前向神经网络
net_1=newff(minmax(P),[10,1],{
    
    'tansig','purelin'},'traingdm')
%  当前输入层权值和阈值
inputWeights=net_1.IW{
    
    1,1}
inputbias=net_1.b{
    
    1}
%  当前网络层权值和阈值
layerWeights=net_1.LW{
    
    2,1}
layerbias=net_1.b{
    
    2}
%  设置训练参数
net_1.trainParam.show = 50;
net_1.trainParam.lr = 0.01;
net_1.trainParam.mc = 0.9;
net_1.trainParam.epochs = 60000;
net_1.trainParam.goal = 1e-3;
%  调用 TRAINGDM 算法训练 BP 网络
[net_1,tr]=train(net_1,P,T);
%BP 网络进行仿真
A = sim(net_1,P);
%  计算仿真误差
E = T - A;
mse(E)
%BP神经网络测试
%加载保存好的神经网络
A = sim(net_1,p)
%四舍五入结果
result=round(A)
%显示判断结果
num3=0;
direction='方向';
s=struct('direction',direction);
for num0=1:sample_num
if (num0<=2)
if result(num0)==1
s(num0).direction='右';
end
end
if (num0>2&&num0<=4)
if result(num0)==2
s(num0).direction='中右';
end
end
if (num0>4&&num0<=6)
if result(num0)==3
s(num0).direction='中间';
end
end
if (num0>6&&num0<=8)
if result(num0)==4
s(num0).direction='中左';
end
end
if (num0>8&&num0<=10)
if result(num0)==5
s(num0).direction='左';
end
end
end
%显示结果
for num1=1:N_train
for num2=1:M_train
num3=num3+1;
consequence=sprintf('图%d-%d人脸朝%s方向',num2+8,num1,s(num3).direction)
str=strcat('D:\复习教材\神经网络\3 BP神经网络\program\Images\',num2str(num2+8),'_',num2str(num1),'.bmp'); %读取图像,连接字符串形成图像的文件名。
str1=consequence;
img= imread(str);
[rows cols]= size(img);%获得图像的行和列值。
img_edge=edge(img,'Sobel');
k=k+1;
subplot(M_train,N_train,k);
imshow(img_edge);%显示灰度图
title(consequence);
end
end
%显示正确率
correct_rate=[];
for num4=1:sample_num
if s(num4).direction~=0
correct_rate(num4)=1;
else
correct_rate(num4)=0;
end
end
sum1=sum(correct_rate(:));
correct_rate1=sum1/sample_num*100;
sprintf('识别正确率为 %d%%',correct_rate1)

三、结果展示
在这里插入图片描述
可以看到整个人脸朝向识别为100%。

猜你喜欢

转载自blog.csdn.net/qq_42955211/article/details/106572622