【字符识别】基于matlab BP神经网络字符识别【含Matlab源码 1358期】
一、手写数字识别技术简介
1 案例背景
手写体数字识别是图像识别学科下的一个分支,是图像处理和模式识别研究领域的重要应用之一,并且具有很强的通用性。由于手写体数字的随意性很大,如笔画粗细、字体大小、倾斜角度等因素都有可能直接影响到字符的识别准确率,所以手写体数字识别是一个很有挑战性的课题。在过去的数十年中,研究者们提出了许多识别方法,并取得了一定的成果。手写体数字识别的实用性很强,在大规模数据统计如例行年检、人口普查、财务、税务、邮件分拣等应用领域都有广阔的应用前景"。
本案例讲述了图像中手写阿拉伯数字的识别过程,对手写数字识别的基于统计的方法进行了简要介绍和分析,并通过开发一个小型的手写体数字识别系统来进行实验。手写数字识别系统需要实现手写数字图像的读取功能、特征提取功能、数字的模板特征库的建立功能及识别功能。
2 BP算法与实现过程
2.1 BP算法基本原理
将已知输入向量和相应的输出向量(期望输出)作为训练样本,并假定即将学习的网络已被赋予一组权值。为消除梯度幅度的不利影响,利用弹性反向传播算法通过过如下步骤更新权值(图1):首先,使用初始权值(不管正确与否)从输入层开始向前传播,计算出所有神经元的输出,这样输出层的输出与期望输出(即输出值与目标值)之间存在较大的误差。然后,计算作为神经元权值函数的]误差函数(损失函数或目标函数、代价函数)的梯度,根据误差降低最快的方向来调整更新权值,通过将输出误差反向传播给隐含层来不断调整误差函数。在计算误差梯度的同时,使用与上面同样的方法更新隐含层的权值。反复迭代更新,直到损失函数达到预定的理想目标。在弹性反向传播算法的学习过程中,权值的修正值即为学习率,而梯度只影影响权值变化的方向,即正负。
图1 反向传播神经网络模型
1.2 感知器神经网络
感知器(multilayer perceptron, MLP) 神经网络是模式识别的简单二元分类人工网络, 它通过权值模仿神经细胞的突触,用激活函数模仿细胞体,偏置即为阈值。单层的感知器网络结构如图2所示。单层感知器可将外部输入x分成两类:当感知器的输出y为正数或零时,输入属于第一类;当感知器的输出为负数时,输入属于第二类。
1.3 实现过程
(1)图像读取
在本文中,设计并自建了样本的数据库,库中有0~9共10个阿拉伯数字的5000张不同的手写数字图像,均为白底黑色的bmp格式的文件, 每个数字对应500张图片。实验要从每一个数字中都随机选取450张手写图像作为训练样本,每一个数字剩下的50张作为测试样本。部分数字样张如图3所示。
图3 数字样张
(2)提取特征
本设计中的训练样本数量多,而而一般神经网络输入层的神经元数就是训练样本向量的维数,因此需要对训练样本向量做降维预处理。预处理过程就是通过灰度阈值函数将图像转换成二值图像。降维前需先将所有图像做一次缩放,以确保每个图像的输入向量都具有相同的像素。本设计选定图像缩放的高度和宽度分别为70像素点和50像素点,符合一般手写阿拉伯数字的高宽比。对这些缩放后的图像作纵横切割,如图4所示,每10×10个像素点作为一系列像素块,构成一张包含35个像素块的二值图像计算每一个像素块中0和1的占比,并用它作为模式的一个特征值,这样可以构成5x7的特征值矩阵。考虑到感知器神申经网络输入向量只能是一维,故需要将此矩阵转换成一维向量作为训练样本的输入,转置后共生成35个一维向量。
图4 缩放后的图像切割
(3)构造标签
无论是训练样本还是测试样本,都需要构造标签,前者用于映射的学习,后者用于判断训练网络的正确率。一般地,输出层神经元个数即为分类网络中的分类类别数。阿拉伯数字是10类,故输出神经元数为10。每个类由具体的500个图像构成,包含训练样本和测试样本。通过提取特征每个类均生成35个一维向量:用500个列向量(1000000000)T来标注模式1,即数字1;(0100000000)标注模式2,即数字2;(0010000000)标注模式3,即数字3;依此类推,最后的(0000000001)标注模式0,即数字0。运行代码如下:
(4)随机选定训练样本和测试样本测试
利用MATLAB中已有的rand()伪随机数生成函数来生成5000个介于0和1之间的伪随机数。将生成的伪随机数做升序排序,通过索引来记录随机数原来的位置,并将原来的位置组合成新的行向量。在本设计中,输入层的神经元有35个,输出层神经元有10个,选取25为中间隐含层神经元个数。
(5)数字识别与正确率的计算
对比测试前的标签和仿真后的输出,用测试前的标签值减去输出值,得到误差值,将误差为0的视为正确识别,求出神经网络的正确率。具体运行代码如下:
二、部分源代码
clc; clear all; close all;
warning off all;
% 获取字符集
fd = fullfile(pwd, 'images', 'dbx');
fds = dir(fd);
ts = [];
for i = 1 : length(fds)
if isequal(fds(i).name, '.') || isequal(fds(i).name, '..')
continue;
end
ts{end+1} = fds(i).name;
end
files = GetAllFiles(fd);
% 提取字符集合的特征向量
db_file = fullfile(pwd, 'VL.mat');
if exist(db_file, 'file')
load(db_file);
else
VT = [];
LT = [];
for i = 1 : length(files)
im = imread(files{i});
[~, v] = get_feature(im);
% 特征
VT = [VT v];
[pn, ~, ~] = fileparts(files{i});
[~, nm, ~] = fileparts(pn);
for j = 1 : length(ts)
if isequal(ts{j}, nm)
% 标签
LT = [LT j];
break;
end
end
end
save(db_file, 'VT', 'LT');
end
% BP训练
net_file = fullfile(pwd, 'bp_net.mat');
if exist(net_file, 'file')
load(net_file);
else
p_train=VT;
t_train=LT;
[pn,minp,maxp,tn,mint,maxt] = premnmx(p_train, t_train);
threshold=minmax(pn);
net=newff(threshold,[30,20,10,1],{'tansig','tansig','tansig','purelin'},'trainlm');
net.trainParam.epochs=10000;
net.trainParam.goal=1e-5;
net.trainParam.show=50;
net.trainParam.lr=0.01;
net=train(net,pn,tn);
% 存储网络
save(net_file, 'net', 'minp', 'maxp', 'mint', 'maxt');
end
m=1;%图片的亮度系数对与识别成功率影响很大,如果图片本身对比度很高(你的图片的对比度就很高)值设为1即可,如果光线较暗可适当提高数值反之亦然。
%类似我文件夹中的图片,需将m设置为0.5~0.3,否则连续域处理无法实现程序无法响应
[fn,pn,fi]=uigetfile('*.jpg','选择图片'); %选择图片
I=imread([pn fn]);figure(1),imshow(I);title('原始图像');%显示原始图像
%J=imadjust(I,[0.2 0.6],[0 1],m);figure(2),imshow(J);title('灰度图像'); %调整图像灰度并调高亮度
grayimg = I;BWimg = grayimg;[width,height]=size(grayimg);%灰度图数据传递,导入宽高
%thresh = graythresh(I); %自动确定二值化阈值;
A=im2bw(I,0.6); % thresh=0.5 表示将灰度等级在128以下的像素全部变为黑色,将灰度等级在128以上的像素全部变为白色。
figure(3);imshow(A);title('二值化图像');%显示图像
bw = edge(A,'sobel','vertical'); figure(4); imshow(bw);title('边缘图像'); % 垂直边缘检测
Z = strel('rectangle',[30,18]);%连通域处理
bw_close=imclose(bw,Z);figure(5);imshow(bw_close);title('闭操作');%连通域闭处理
%bw_open = imopen(bw,Z);figure(6);imshow(bw_open );title("开操作");%连通域开处理
showImg = grayimg;%灰度图数据传递
%图像数据二值化处理,如果图像尺度过大会使处理时间几何倍增加,所以尽量使用小尺度图片,(你的图片完全OK)我提供个测试图片就属于过大的了
for i=1:width
for j=1:height
if(BWimg(i,j) == 255)
showImg(i,j)= grayimg(i,j);
else
showImg(i,j)= 0;
end
end
end
figure(6);
imshow(showImg);%可视化显示二值化图像
[l,m] = bwlabel(bw_close); %连续域标签
status=regionprops(l,'BoundingBox');%图像区域度量
centroid = regionprops(l,'Centroid');%字符区域度量
imshow(I);hold on;
a=[-7,-7,7,7];
if m>1
for i=1:m
if status(i).BoundingBox(1,3) > status(i).BoundingBox(1,4)%归一化预处理
status(i).BoundingBox(1,4)=status(i).BoundingBox(1,3);
else
status(i).BoundingBox(1,3)=status(i).BoundingBox(1,4);
end
status(i).BoundingBox=status(i).BoundingBox+a;
rectangle('position',status(i).BoundingBox,'edgecolor','g');%字符画框
text(centroid(i,1).Centroid(1,1)-25,centroid(i,1).Centroid(1,2)-25, num2str(i),'Color', 'r') %字符框标号
end
for i=1:m
cropimg_2 = imcrop(A,status(i).BoundingBox);%画框部分图像截取
cropimg_2 = imresize(cropimg_2,[28,28]); %将图像调整为28*28的
%cropimg_2 = imcomplement(cropimg_2);
[file_path,~,~]= fileparts(mfilename('fullpath'));
disp(file_path)
imwrite(cropimg_2,[file_path,'\\LXJC\\',num2str(m,'%02d'),'.bmp'],'bmp')%将截取部分的图像暂时存储在LXSB文件中
filePath = [file_path,'\\LXJC\\',num2str(m,'%02d'),'.bmp'];%打开图像
if isequal(filePath, 0)
break;
end
[~, p_test] = get_feature(im);
p2n = tramnmx(p_test,minp, maxp);
r=sim(net,p2n);
r2n = postmnmx(r,mint,maxt);
r = ts{r};
figure;imshow(cropimg_2);title(r, 'FontSize', 16);
end
else
end
function [bwz, p] = get_feature(im)
% 计算特征向量
bw = im2bw(im,graythresh(im));
bw = ~bw;
[r, c] = find(bw);
rect = [min(c)-1 min(r)-1 max(c)-min(c)+2 max(r)-min(r)+2];
bwt = imcrop(bw, rect);
rate = 70/size(bwt, 1);
rc = round(size(bwt)*rate);
bwt = imresize(bwt, rc, 'bilinear');
if size(bwt, 2) < 50
bwz = zeros(70, 50);
ss = round((size(bwz, 2)-size(bwt,2))*0.5);
tt = round((size(bwz, 1)-size(bwt,1))*0.5);
bwz(:, ss:ss+size(bwt,2)-1) = bwt;
else
bwz = imresize(bwt, [70 50], 'bilinear');
end
bwz = logical(bwz);
for k=1:7
for k2=1:5
dt=sum(bwz(((k*10-9):(k*10)),((k2*10-9):(k2*10))));
f((k-1)*5+k2)=sum(dt);
end
end
f=((100-f)/100);
p = f(:);
function filePath = OpenImageFile(imgfilePath)
% 打开文件
% 输出参数:
% filePath——文件路径
if nargin < 1
imgfilePath = fullfile(pwd, 'images/testx/Ⅰ-003.bmp');
end
% 读取文件
[filename, pathname, ~] = uigetfile( ...
{ '*.bmp;*.jpg;*.tif;*.png;*.gif','All Image Files';...
'*.*', '所有文件 (*.*)'}, ...
'选择文件', ...
'MultiSelect', 'off', ...
imgfilePath);
filePath = 0;
return;
end
filePath = fullfile(pathname, filename);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
三、运行结果
四、matlab版本及参考文献
1 matlab版本
2014a
2 参考文献
[1] 蔡利梅.MATLAB图像处理——理论、算法与实例分析[M].清华大学出版社,2020.
[2]杨丹,赵海滨,龙哲.MATLAB图像处理实例详解[M].清华大学出版社,2013.
[3]周品.MATLAB图像处理与图形用户界面设计[M].清华大学出版社,2013.
[4]刘成龙.精通MATLAB图像处理[M].清华大学出版社,2015.
文章来源: qq912100926.blog.csdn.net,作者:海神之光,版权归原作者所有,如需转载,请联系作者。
原文链接:qq912100926.blog.csdn.net/article/details/120616219
- 点赞
- 收藏
- 关注作者
评论(0)