基于人工神经网络的MATLAB手写数字识别系统
- 函数MouseDraw实现手写识别系统GUI界面的建立和鼠标手写的实现。(使用时保存为MouseDraw.m)
function MouseDraw(action)
% MouseDraw 本例展示如何以Handle Graphics来设定滑鼠事件
% (MouseDraw Events)的反应指令(Callbacks)
% 本程序在鼠标移动非常快时,不会造成画“断线”
% global不能传矩阵
global InitialX InitialY FigHandle hb2 hb3 hb4 count hb5 hb6 hb7
count='E:\im.jpg';
imSize = 50;
if nargin == 0, action = 'start';
end
switch(action)
%%开启图形视窗
case 'start',
FigHandle = figure('WindowButtonDownFcn','MouseDraw down','DeleteFcn','save bpnet');
axis([1 imSize 1 imSize]); % 设定图轴范围%
set(gca,'Position',[.25 .20 .7 .7]);
axis off;
grid off;
box on; % 将图轴加上图框
title('手写体输入窗');
try evalin('base','load bpnet')
catch
evalin('base','bpgdtrain');
end
% % fprintf('start');
%%设定滑鼠按钮被按下时的反应指令为「MouseDraw down」
% set(gcf, 'WindowButtonDownFcn', 'MouseDraw down');
hb1 = uicontrol('Parent', FigHandle, 'Units', 'Normalized', ...
'Position', [.3 .01 .13 .07], 'String', '保存', ...
'Callback',['exa=rgb2gray(frame2im(getframe(gca)));','imwrite(exa,''E:\im.jpg'')']);
hb2=uicontrol('Parent',FigHandle,'Style','popupmenu','Position',[50 50 50 30],...
'String', {'26','24', '22', '20', '18', '16','14','12','10'});
hb3=uicontrol('Parent', FigHandle,'Style','text',...
'Position',[10 90 90 30],'String',[ 'CurrentX() ','CurrentY()']);
hb4=uicontrol('Parent',FigHandle,'Style','popupmenu','Position',[50 20 50 30],...
'String',{'Red','Blue','Black','Yellow','Green'});
uicontrol('Parent',FigHandle,'Position',[270 6 70 30],'String','训练','Callback',...
['exa=rgb2gray(frame2im(getframe(gca)));','sample=reshape(recgnition(exa),25,1);','clc;',...
't=inputdlg(''数字类别'',''样品训练'');','t=str2num(t{1,1})/10;',...
'bpnet.trainParam.lr=str2num(get(hb6,''String''));','bpnet.trainParam.goal=str2num(get(hb7,''String''));',...
'[bpnet]=train(bpnet,sample,t);','save bpnet']);
uicontrol('Parent',FigHandle,'Position',[360 6 70 30],'String','识别','Callback',...
['exa=rgb2gray(frame2im(getframe(gca)));','sample=reshape(recgnition(exa),25,1);',...
'record=round(sim(bpnet,sample)*10);','clc;','set(hb5,''String'',num2str(record),''fontSize'',48);']);
uicontrol('Parent',FigHandle,'Style','text','Position',[10 60 30 20],'String','字号');
uicontrol('Parent',FigHandle,'Style','text','Position',[10 30 30 20],'String','颜色');
hb5=uicontrol('Parent',FigHandle,'Style','text','Position',[10 150 90 90]);
uicontrol('Parent',FigHandle,'Style','text','Position',[5 260 50 20],'String','学习速率');
hb6=uicontrol('Parent',FigHandle,'Style','Edit','Position',[60 260 30 20],'String','0.01');
uicontrol('Parent',FigHandle,'Style','text','Position',[5 290 50 20],'String','训练精度');
hb7=uicontrol('Parent',FigHandle,'Style','Edit','Position',[60 290 30 20],'String','0.005');
uicontrol('Parent',FigHandle,'Style','pushbutton','Position',[450 6 70 30],'String','清除','Callback','cla');
%将函数变量导入到工作空间;
assignin('base','hb5',hb5);
assignin('base','hb6',hb6);
assignin('base','hb7',hb7);
%%%%%%%%%%%%%%%%%%%%%%%%%%%
dlmwrite('IXT.txt', -10, 'delimiter', '\t', 'precision', 6);
dlmwrite('IYT.txt', -10, 'delimiter', '\t', 'precision', 6); %%滑鼠按钮被按下时的反应指令
case 'down',
if strcmp(get(FigHandle, 'SelectionType'), 'normal') %如果是左键
set(FigHandle,'pointer','hand');
CurPiont = get(gca, 'CurrentPoint');
InitialX = CurPiont(1,1);
InitialY = CurPiont(1,2);
dlmwrite('IXT.txt', InitialX, '-append', 'delimiter', '\t', 'precision', 6);
dlmwrite('IYT.txt', InitialY, '-append', 'delimiter', '\t', 'precision', 6);
% 列印「MouseDraw down!」讯息
% % fprintf('MouseDraw down!\n');
% 设定滑鼠移动时的反应指令为「MouseDraw move」
set(gcf, 'WindowButtonMotionFcn', 'MouseDraw move');
set(gcf, 'WindowButtonUpFcn', 'MouseDraw up');
elseif strcmp(get(FigHandle, 'SelectionType'), 'alt') % 如果是右键
set(FigHandle, 'Pointer', 'arrow');
set( FigHandle, 'WindowButtonMotionFcn', '')
set(FigHandle, 'WindowButtonUpFcn', '')
fprintf('MouseDraw right button down!\n');
ImageX = importdata('IXT.txt');
ImageY = importdata('IYT.txt');
InputImage = ones(imSize);
roundX = round(ImageX);
roundY = round(ImageY);
for k = 1:size(ImageX,1)
if 0<roundX(k) && roundX(k)<imSize && 0<roundY(k) && roundY(k)<imSize
InputImage(roundX(k)-1:roundX(k)+2, roundY(k)-1:roundY(k)+2) = 0;
end
end
InputImage = imrotate(InputImage,90); % 图像旋转90
figure(2);
imshow(InputImage);
end
%%滑鼠移动时的反应指令
case 'move',
CurPiont = get(gca, 'CurrentPoint');
X = CurPiont(1,1);
Y = CurPiont(1,2);
set(hb3,'String',['CurrentX(',num2str(X),')','CurrentY(',num2str(Y),')']);
% 当鼠标移动较快时,不会出现离散点。
% 利用y=kx+b直线方程实现。
x_gap = 0.1;
% 定义x方向增量
y_gap = 0.1;
% 定义y方向增量
if X > InitialX
step_x = x_gap;
else
step_x = -x_gap;
end
if Y > InitialY
step_y = y_gap;
else
step_y = -y_gap;
end
% 定义x,y的变化范围和步长
if abs(X-InitialX) < 0.01 % 线平行于y轴,即斜率不存在时
iy = InitialY:step_y:Y;
ix = X.*ones(1,size(iy,2));
else
ix = InitialX:step_x:X ;
% 定义x的变化范围和步长 % 当斜率存在,即k = (Y-InitialY)/(X-InitialX) ~= 0
iy = (Y-InitialY)/(X-InitialX).*(ix-InitialX)+InitialY;
end
ImageX = [ix, X];
ImageY = cat(2, iy, Y);
popup_index1=26-(get(hb2,'Value')-1)*2;
popup_index2=get(hb4,'Value');
switch(popup_index2)
case 1
line(ImageX,ImageY, 'marker', '.', 'markerSize',popup_index1, ...
'LineStyle', '-', 'LineWidth', 4, 'Color', 'Red');
case 2
line(ImageX,ImageY, 'marker', '.', 'markerSize',popup_index1, ...
'LineStyle', '-', 'LineWidth', 4, 'Color', 'Blue');
case 3
line(ImageX,ImageY, 'marker', '.', 'markerSize',popup_index1, ...
'LineStyle', '-', 'LineWidth', 4, 'Color', 'Black');
case 4
line(ImageX,ImageY, 'marker', '.', 'markerSize',popup_index1, ...
'LineStyle', '-', 'LineWidth', 4, 'Color', 'Yellow');
case 5
line(ImageX,ImageY, 'marker', '.', 'markerSize',popup_index1, ...
'LineStyle', '-', 'LineWidth', 4, 'Color', 'Green');
end
dlmwrite('IXT.txt', ImageX, '-append', 'delimiter', '\t', 'precision', 6);
dlmwrite('IYT.txt', ImageY, '-append', 'delimiter', '\t', 'precision', 6);
InitialX = X; %记住当前点坐标
InitialY = Y; %记住当前点坐标
% 列印「MouseDraw is moving!」及滑鼠现在位置
% fprintf('MouseDraw is moving! Current location = (%g, %g)\n', ...
% CurPiont(1,1), CurPiont(1,2));
% % fprintf('MouseDraw move!\n');
% 设定滑鼠按钮被释放时的反应指令为「MouseDraw up」
set(gcf, 'WindowButtonUpFcn', 'MouseDraw up');
%%滑鼠按钮被释放时的反应指令
case 'up',
% 清除滑鼠移动时的反应指令
set(gcf, 'WindowButtonMotionFcn', '');
% 清除滑鼠按钮被释放时的反应指令
set(gcf, 'WindowButtonUpFcn', '');
% 列印「MouseDraw up!」
% % fprintf('MouseDraw up!\n');
end
end
- 实现手写数字图像特征的提取:(存为recgnition.m)
function sample=recgnition(exa)
[i,j]=find(exa~=204);
imin=min(i);
imax=max(i);
jmin=min(j);
jmax=max(j);
a=exa(imin:imax,jmin:jmax);
M=imax-imin+1;
N=jmax-jmin+1;
for m=1:5
for n=1:5
exa_c{m,n}=a(1+(m-1)*M/5:m*M/5,1+(n-1)*N/5:n*N/5);
sample(1,(m-1)*5+n)=size(find(exa_c{m,n}~=204),1)/(M*N/25);
%subplot(5,5,(m-1)*5+n),subimage(exa_c{m,n});
end
end
- 建立bp神经网络。(可修改所建立bp神经网络参数,也可建立其他类型神经网络)。
x=ones(25,2);
x(:,1)=0;
bpnet=newff(x,[50,1],{'logsig','logsig'},'traingd');
bpnet.trainParam.show=5;%显示训练迭代过程(每隔5次训练,显示一次训练进程)
bpnet.trainParam.lr=0.01;%学习速率
bpnet.trainParam.epochs=2000;%最大训练次数
bpnet.trainParam.goal=0.005;%训练要求精度(0.005)
此段命令应存为bpgdtrain.m文件。
以上函数以及m文件须保存以后才可调用。
神经网络要经过一定数量的训练才能达到较高的识别精度。
使用时先运行MouseDraw函数,出现下图界面,
界面介绍:
保存:可将手写数字图像保存为im.jpg文件。
训练:用于有导师训练神经网络,用户使用鼠标写好数字,点击训练,弹出输入框框,输入相应正确数字。
识别:对界面上的手写数字进行识别,结果显示在左边白色方框。
清除:可清除界面上数字,重新书写。
字号、颜色选择下拉框可选择手写数字字号与颜色。
控制训练精度和学习速率。具体参照bp神经网络。