基于深度学习的手写数字实现及超简单的英文字母识别

本文章大致分为5个板块,分别是MNIST数据库,深度学习神经网络的构建,图像预处理,图像识别,简单的英文字母识别展示。

1.MNIST数据库

总所周知,MNIST数据库是专门用于为手写数字识别系统提供数据库的,本手写数字识别系统所利用的MNIST数据库来自于http://yann.lecun.com/exdb/mnist/网站,需要将网站中的四个文件都给下载下来。该MNIST数据库中含有60000张手写数字图片,每一张图片的大小都为28*28,而且10000张图片用于测试,50000张图片用于训练。

2.深度学习网络的构建

本深度学习网络的构建利用到的是Matlab R2020a版本,其中有一个软件叫做deepNetworkDesigner,这是该版本的Matlab软件所自带的。

接下来就是深度学习网络的构建,其结构图如下所示:

 其中的参数设置,imageinput的参数inputsize更改为28,28,1;conv的参数filterSzie更改为5,5,然后Numfilter更改为6;maxpool的参数PoolSize和Stride都更改为2,2;conv的参数filterSzie更改为5,5,然后Numfilter更改为16;fc的参数OutputSize更改为120;fc的参数OutputSize更改为84;fc的参数OutputSize更改为10。(以上按照图中的连接顺序进行说明,若未提及,则不需要更改参数。)最后将该结构导出为代码,此处只是为了参照结构设置是否正确,完整的代码会在后面呈现。

layers = [
    imageInputLayer([28 28 1],"Name","imageinput")
    convolution2dLayer([5 5],6,"Name","conv_1","Padding","same")
    tanhLayer("Name","tanh_1")
    maxPooling2dLayer([2 2],"Name","maxpool_1","Padding","same","Stride",[2 2])
    convolution2dLayer([5 5],16,"Name","conv_2","Padding","same")
    tanhLayer("Name","tanh_2")
    maxPooling2dLayer([2 2],"Name","maxpool_2","Padding","same","Stride",[2 2])
    fullyConnectedLayer(120,"Name","fc_1")
    fullyConnectedLayer(84,"Name","fc_2")
    fullyConnectedLayer(10,"Name","fc_3")
    softmaxLayer("Name","softmax")
    classificationLayer("Name","classoutput")];

3.图像预处理

本手写数字识别系统的预处理部分的代码涉及到图像规范化、图像去噪处理、图像二值化、图像膨胀处理,并将此部分代码命名为s3_。

%% 图像规范化
%初始化,读入图像,图像数据为m*n*color
test_image=X;
imshow(test_image);
img=test_image;

%变化后的图像
[row,col,color] = size(img);%获得图像的行列数及色板数
row = round(row*3);%新图像的行
col = round(col*3);%新图像的列

%使新图像初始化
%使用class获得原图像的数据类型,使得新图像得数据类型与原图像相同
img_new=zeros(row,col,color,class(img));

%对新图像的行列色板赋色
for i = 1:row
    for j = 1:col
        for n = 1:color
            x = round(i/3);
            y = round(j/3);
            %为了防止x和y为0,对x和y进行加一处理
            if x == 0
                x = 1+x;
            end
            if y == 0
                y = y+1;
            end
            img_new(i,j,n) = img(x,y,n);
        end
    end
end

test_image=img_new;

%% 图像去噪处理 中值滤波法
% test_image1 = imnoise(test_image,'salt & pepper',0.02)
% test_image2 = medfilt3(test_image1)
% 
% test_image = imnoise(test_image,'salt&pepper',0.02)
test_image = medfilt3(test_image);




%% 图像二值化
shape = size(test_image);
dimension = numel(shape);
if dimension > 2
    test_image = rgb2gray(test_image);
end
test_image = imresize(test_image,[28,28]);
test_image = imbinarize(test_image,0.8);
test_image = imcomplement(test_image);
% % 显示原图像
% figure;
% imshow(test_image);
% title("Original Image");
%% 图像膨胀

B=[0 1 0;1 1 1;0 1 0];
Z=imdilate(test_image,B);
test_image = Z;
% % 显示新图像
% figure;
% imshow(Z);
% title("New Image");
axes(h3);
imshow(test_image);

 4.图像识别

代码呈现:

此部分代码命名为s1

datapath="./Mnist/";

filenameImagesTrain=strcat(datapath,'train-images-idx3-ubyte');
filenameLabelsTrain=strcat(datapath,'train-labels-idx1-ubyte');
filenameImagesTest=strcat(datapath,'t10k-images-idx3-ubyte');
fielnameLabelsTest=strcat(datapath,'t10k-labels-idx1-ubyte');

XTrain=processMNISTimages(filenameImagesTrain);
YTrain=processMNISTlabels(filenameLabelsTrain);
XTest=processMNISTimages(filenameImagesTest);
YTest=processMNISTlabels(fielnameLabelsTest);

%%
% 搭建神经网络
layers = [
    imageInputLayer([28 28 1],"Name","imageinput")
    convolution2dLayer([5 5],6,"Name","conv_1","Padding","same")
    tanhLayer("Name","tanh_1")
    maxPooling2dLayer([2 2],"Name","maxpool_1","Padding","same","Stride",[2 2])
    convolution2dLayer([5 5],16,"Name","conv_2","Padding","same")
    tanhLayer("Name","tanh_2")
    maxPooling2dLayer([2 2],"Name","maxpool_2","Padding","same","Stride",[2 2])
    fullyConnectedLayer(120,"Name","fc_1")
    fullyConnectedLayer(80,"Name","fc_2")
    fullyConnectedLayer(10,"Name","fc_3")
    softmaxLayer("Name","softmax")
    classificationLayer("Name","classoutput")];

options=trainingOptions('sgdm',...%优化器
    'LearnRateSchedule','piecewise',...%学习率
    'LearnRateDropFactor',0.2,...%
    'LearnRateDropPeriod',5,...
    'MaxEpochs',20,...%最大学习整个数据集的次数
    'MiniBatchSize',128,...%每次学习样本数
    'Plots','training-progress');%画出整个训练过程


doTraining = true;
if doTraining
    trainNet=trainNetwork(XTrain,YTrain,layers,options);
end
save Minist_LeNet5 trainNet;%保存训练后的模型
yTest=classify(trainNet,XTest);
accuracy=sum(yTest==YTest)/numel(YTest);

%% 
% 处理Mnist数据集图像
function X = processMNISTimages(filename)
    [fileID,errmsg] = fopen(filename,'r','b');
    if fileID < 0
        error(errmsg);
    end
    magicNum = fread(fileID,1,'int32',0,'b');
    if magicNum == 2051
        fprintf('\nRead MNIST image data...\n')
    end
    numImages = fread(fileID,1,'int32',0,'b');
    fprintf('Number of images in the dataset: %6d ...\n',numImages);
    numRows = fread(fileID,1,'int32',0,'b');
    numCols = fread(fileID,1,'int32',0,'b');
    X = fread(fileID,inf,'unsigned char');
    X = reshape(X,numCols,numRows,numImages);
    X = permute(X,[2 1 3]);
    X = X./255;
    X = reshape(X, [28,28,1,size(X,3)]);
%     X = dlarray(X, 'SSCB');
    fclose(fileID);
end
% 处理Mnist数据集标签
function Y = processMNISTlabels(filename)
    [fileID,errmsg] = fopen(filename,'r','b');
    if fileID < 0
        error(errmsg);
    end
    magicNum = fread(fileID,1,'int32',0,'b');
    if magicNum == 2049
        fprintf('\nRead MNIST label data...\n')
    end
    numItems = fread(fileID,1,'int32',0,'b');
    fprintf('Number of labels in the dataset: %6d ...\n',numItems);
    Y = fread(fileID,inf,'unsigned char');
    Y = categorical(Y);
    fclose(fileID);
end

此部分代码命名为s5

load('Minist_LeNet5.mat');
%test_result = Recognition(trainNet, test_image);
test_result = classify(trainNet, test_image);

ch=test_result;
set(h6,'String',ch,...
    'FontSize',30);

此部分代码命名为s6

%op
%读取图像文件,用对话框方式读取文件。
[filename,pathname]=uigetfile({'*.bmp';'*.jpg';'*.png';...
    '*.gif';'*.*'},...
    'Pick an Image File');    
X=imread([pathname,filename]);
%显示图像
axes(h0);%将h0设置为当前坐标轴句柄
imshow(X);%在h0上显示原始图像

交互界面代码命名为smain,可以直接运行(如果上述操作正确的话)

clear all
   clc;
%形成用户界面
clear all;
%添加图形窗口
H=figure('Color',[0 1 0],...
    'position',[400 300 500 400],...
    'Name','基于深度学习神经网络的手写数字识别',...
    'NumberTitle','off',...
    'MenuBar','none');
%画坐标轴对象,显示原始图像
h0=axes('position',[0.1 0.6 0.3 0.3]);
%添加训练神经网络按钮
h1=uicontrol(H,'Style','push',...       %uicontrol(user interface control,用户界面控制),包括按钮、滑标、文本框及弹出式菜单
    'Position',[280 300 80 60],...
    'String','网络训练',...
    'FontSize',14,...
    'Call','s1');
%添加图像打开按钮
h2=uicontrol(H,'Style','push',...
    'Position',[380 300 80 60],...
    'String','选择图片',...
    'FontSize',14,...
    'Call','s6');
%画坐标轴对象,显示经过预处理之后的图像
h3=axes('position',[0.1 0.2 0.3 0.3]);
%添加预处理按钮
h4=uicontrol(H,'Style','push',...
    'Position',[380 200 80 60],...
    'String','图像预处理',...
    'FontSize',10,...
    'Call','s3_');
%添加识别按钮
h5=uicontrol(H,'Style','push',...
    'Position',[350 100 80 60],...
    'String','数字识别',...
    'FontSize',14,...
    'Call','s5');
%添加显示识别结果的文本框
h6=uicontrol(H,'Style','text',...
    'Position',[250 10 100 80],...
    'String','识别结果',...
    'FontSize',16,...    
    'Fore',[0 0 1]);

 5.简单英文字母识别展示

这个程序比较垃圾,我个人的理解是只能识别给定图片的26张英文字母。慎用,还需改进。

此部分代码命名为y0

%open
%读取文件
[filename,pathname] =uigetfile({'*.bmp';'*.png';'*.jpg';'*.gif';'*.*'},...
    'Pick an image File');
X=imread([pathname,filename]);
axes(h0);
imshow(X);

 此部分代码命名为y1

%y1
M = 1;%人数
N = M*26;%样本数
%获取26个大写英文字母的数据
for kk = 0:N-1
    p1 = ones(16,16);%初始化16*16的二值化图像
    m = strcat('word\',int2str(kk),'.bmp');%形成文件名
    x = imread(m,'bmp');%读取图像
    bw = im2bw(x,0.5);%对图像进行二值化处理
    %用矩形截取
    [i,j] = find(bw==0);%查找像素为黑色的坐标
    %取边界坐标
    imin = min(i);
    jmin = min(j);
    imax = max(i);
    jmax = max(j);
    bw1 = bw(imin:imax,jmin:jmax);%截取
    %调整比例,使其缩放成16*16
    rate = 16/max(size(bw1));
    bw1 = imresize(bw1,rate);%会存在转换误差
    %将图像转化为16*16
    [i,j] = size(bw1);
    i1 = round((16-i)/2);
    j1 = round((16-j)/2);
    p1(i1+1:i1+i,j1+1:j1+j) = bw1;
    p1 = -1.*p1+ones(16,16);
    %将p1转换成输入向量
    for m = 0:15
        p(m*16+1:(m+1)*16,kk+1) = p1(1:16,m+1);
    end
end
%形成目标向量
for kk = 0:M-1
    for ii = 0:25
        t(kk+ii+1) = ii;
    end
end
%设置输入向量
pr(1:256,1) = 0;
pr(1:256,2) = 1;
net = newff(pr,[25 1],{'logsig' 'purelin'},'traingdx','learngdm');
net.trainParam.epochs = 2500;
net.trainParam.goal = 0.001;
net.trainParam.show = 10;
net.trainParam.lr = 0.05;

net = train(net,p,t);
 save E53net net;

 此部分代码命名为y2


p(1:256,1)=1;
load E53net net;%加载训练后的BP网络
p1 = ones(16,16);%初始化16*16的二值化图
 bw = im2bw(X,0.5);%对图像进行二值化处理
 %用矩形截取
 [i,j] = find(bw==0);%查找像素为黑色的坐标
    %取边界坐标
   imin=min(i);
imax=max(i);
jmin=min(j);
jmax=max(j);
    bw1 = bw(imin:imax,jmin:jmax);%截取
    %调整比例,使其缩放成16*16
    rate = 16/max(size(bw1));
    bw1 = imresize(bw1,rate);%会存在转换误差
    %将图像转化为16*16
    [i,j] = size(bw1);
    i1 = round((16-i)/2);
    j1 = round((16-j)/2);
    p1(i1+1:i1+i,j1+1:j1+j) = bw1;
    p1 = -1.*p1+ones(16,16);
    
%     B=[0 1 0;1 1 1;0 1 0];
%     p1=imdilate(p1,B);

     axes(h3);
     imshow(p1);

此部分代码命名为y3

%recognize
%生成向量形式
for m=0:15
    q(m*16+1:(m+1)*16,1)=p1(1:16,m+1);
end
%识别
%[a,Pf,Af]=sim(net,q)
a=sim(net,q);
a=round(a);  %取整数
switch a
    case 0,ch='A';
    case 1,ch='B';
    case 2,ch='C';
    case 3,ch='D';
    case 4,ch='E';
    case 5,ch='F';
    case 6,ch='G';
    case 7,ch='H';
    case 8,ch='I';
    case 9,ch='J';
    case 10,ch='K';
    case 11,ch='L';
    case 12,ch='M';
    case 13,ch='N';
    case 14,ch='O';
    case 15,ch='P';
    case 16,ch='Q';
    case 17,ch='R';
    case 18,ch='S';
    case 19,ch='T';
    case 20,ch='U';
    case 21,ch='V';
    case 22,ch='W';
    case 23,ch='X';
    case 24,ch='Y';
    case 25,ch='Z';
end
%显示识别结果
set(h6,'String',ch,...
    'FontSize',30);

此部分代码命名为ymain,可以直接运行。(需要确保有数据库)

clear all
   clc;
%形成用户界面
clear all;
%添加图形窗口
H=figure('Color',[0 1 0],...
    'position',[400 300 500 400],...
    'Name','基于BP学习神经网络的手写英文字母的识别',...
    'NumberTitle','off',...
    'MenuBar','none');
%画坐标轴对象,显示原始图像
h0=axes('position',[0.1 0.6 0.3 0.3]);
%添加训练神经网络按钮
h1=uicontrol(H,'Style','push',...       %uicontrol(user interface control,用户界面控制),包括按钮、滑标、文本框及弹出式菜单
    'Position',[280 300 80 60],...
    'String','网络训练',...
    'FontSize',14,...
    'Call','y1');
%添加图像打开按钮
h2=uicontrol(H,'Style','push',...
    'Position',[380 300 80 60],...
    'String','选择图片',...
    'FontSize',14,...
    'Call','y0');
%画坐标轴对象,显示经过预处理之后的图像
h3=axes('position',[0.1 0.2 0.3 0.3]);
%添加预处理按钮
h4=uicontrol(H,'Style','push',...
    'Position',[380 200 80 60],...
    'String','图像预处理',...
    'FontSize',10,...
    'Call','y2');
%添加识别按钮
h5=uicontrol(H,'Style','push',...
    'Position',[350 100 80 60],...
    'String','英文字母识别',...
    'FontSize',14,...
    'Call','y3');
%添加显示识别结果的文本框
h6=uicontrol(H,'Style','text',...
    'Position',[250 10 100 80],...
    'String','识别结果',...
    'FontSize',16,...    
    'Fore',[0 0 1]);

6.仿真结果显示

  • 2
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值