理论教育 Python实现手写数字识别

Python实现手写数字识别

时间:2023-11-22 理论教育 版权反馈
【摘要】:本节结合Python中简单图像处理技术及神经网络算法,以实现手写阿拉伯数字10个字符的识别为例,说明该类问题的解决方案。图8.4.11手写数字拍照获得的图像,往往存在一些灰色背景,而数字识别时,采用灰度图像处理即可,所以首先需要用Python的图像处理包对图像进行预处理,去除背景。程序:图像灰度直方图对于8.4.11的手写数字图像,得到的灰度直方图如图8.4.12所示。

Python实现手写数字识别

文字识别技术在电子设备上应用很广,属于模式识别技术的一种。其中的阿拉伯数字识别技术相对简单,但其实现过程却足以用于说明图像字符识别的基本原理,它包含了图像特征提取的基本原理与识别算法技术。

本节结合Python中简单图像处理技术及神经网络算法,以实现手写阿拉伯数字10个字符的识别为例,说明该类问题的解决方案

1.图像获取及预处理

在一张白纸中,书写10个数字字符多次,字符行列间保留合理间隙,如图8.4.11所示。

图8.4.11 手写数字

拍照获得的图像,往往存在一些灰色背景,而数字识别时,采用灰度图像处理即可,所以首先需要用Python的图像处理包对图像进行预处理,去除背景。

为了将图像的背景去除,需要先计算图像的灰度直方图确定背景的阈值,其程序代码如下。

程序:图像灰度直方图

对于8.4.11的手写数字图像,得到的灰度直方图如图8.4.12所示。

从图中可以看出,在灰度值143附近,像素点所占比例开始大幅提高,它对应的就是图像的背景像素点。

由此,我们可以将灰度值大于阈值的像素点设置为白色(像素值255),小于阈值的像素点设置为黑色(像素值0),结果就是白色的纸张上写黑色的字,由此定义去除图像背景的函数如下:

图8.4.12 手写数字图像的灰度直方图

def convert_to_bw(im,threshold):#im是图像对象,threshold给定阈值im=im.convert("L") #转换为灰度图像im=im.point(lambda x:255if x>threshold else 0) #代表数字的像素值置0,黑色im=im.convert(ˈ1ˈ) #黑白二值图像im.save(r"e:\sample_1.bmp")return im

程序:数字图像阈值去背景

函数将传递过来的图像im,转换为灰度图像,根据给定的阈值,将图像二值化,并以文件的形式保存。处理结果如图8.4.13所示。

图8.4.13 去除背景后的图像

2.字符分割

接下来的任务是从去除背景后的图像中将各个字符分割出来。

为简化问题,此处采取了一种笨办法,将数字行和列的大致间隔位置用图像处理软件找出来(如windows中的画图),保存到两个向量中,如下面的代码:

定义了xs和ys两个列表后,通过定义如下的函数,将每个字符图像分割出来并以文件的方式保存,函数的代码如下:

处理结果如图8.4.14所示。

图8.4.14 每个字符分割出来后的结果

3.字符标准化

提取出来的每个字符图像,大小不一,字符在小图像中的位置也不一致,这会导致后续提取的字符特征不统一。为提高模型的准确度,我们希望每个字符图像的大小一致(如都是32×32的图像),且字符在图像中居中存放。这个工作用下面的函数完成。

程序:数字标准化

通过上述函数处理,每个字符将保存在一个32×32的小图像中,且字符存储在图像的中间,处理结果如图8.4.15所示。

图8.4.15 标准化的32×32的字符图像

4.字符特征提取

每个字符被标准化为一个32×32的小图像后,为进行建模,需要将小图像表达为数字化的特征。此处采取的策略是:将32×32的小图像分割成256个2×2的小方框,统计每个2×2的小方框中,像素值为0的个数,由此将每个字符表达为256个数字组成的向量。例如,字符4,经过转化后,得到的向量为:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 2 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 4 0

2 0 0 0 0 0 0 0 0 0 0 0 0 3 2 1 4 3 1 0 0 0 0 0 0 0

0 0 0 2 2 3 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 0 0

0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0(www.daowen.com)

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

为了完成特征提取,特定义以下函数,它负责读取每个32×32标准化的小图像,并整理提取特征。

为达到机器学习的目的,每个字符都写了6遍(可能的情况下,写得越多越好),所以共有60个字符,全部转成特征向量后,按行存放,每行256个数字,所以得到一个60行256列的矩阵

5.算法建模

建立特征向量与目标的有效数学模型是数字识别的最后步骤。例如前面整理出来的字符4的特征向量,我们希望算法能建立一个函数关系,当将向量输入函数后,输出的结果是4。可以立即判断出,这种函数关系难以用线性模型描述。

神经网络算法又称为人工神经网络(Artificial Neural Network,ANN),具有很强的非线性拟合能力,是文字识别领域最常用的算法。神经网络算法的结构如图8.4.16所示。

图8.4.16 一个三层的神经网络

网络由输入层、隐含层(隐含层可以有多层)和输出层组成,各节点之间的连线称为权重,权重与对应输入数据乘积加和∑xiwi,通过函数转换得到的结果作为下一层节点的值,该值又作为后续层的输入。输入层和输出层是相对的,例如,隐含层,是输入层的输出层,但又是输出层的输入层。神经网络算法中最著名的是后向传播(Back Propopation,BP)算法,采用的转换函数为sigmoid函数,该函数的定义为:

y=1/(1+e-x)

其函数图形如图8.4.17所示。

图8.4.17 sigmoid函数图形

这意味着,当某个隐层节点,得到所有输入节点与其对应权重的乘积加和值Σxiwi后,将该值经过sigmoid函数转换,就是该节点的输入值。

最后一个问题,是目标函数值的表达模式。神经网络用于模式识别时,目标函数值经常被表达为正交编码。数字识别中共十个字符,分为10种模式,所以其正交编码可以分别表达为:

字符0:1 0 0 0 0 0 0 0 0 0

字符1:0 1 0 0 0 0 0 0 0 0

……

字符9:0 0 0 0 0 0 0 0 0 1

这种正交编码将目标模式所在的位设置为1,其他位全部为0,组成一个向量。

到此,网络拓扑结构即可确定:输入向量有256个数字,因而需要256个节点,输出模式有10种,所以需要10个节点。隐含层节点的设置,是神经网络构造的一个关键,隐层节点数太少,则难以表达好非线性关系,太多又存在过拟合问题。总之,神经网络是一个独立方程数与变量数之间的关系问题,读者可以查阅相关网络构造与训练样本数关系的资料,以求对神经网络有更深入的了解。本例中我们不深入讨论这个问题,将中间隐层节点数设置为64。

关于神经网络算法实现,我们在此选择了sklearn.neural_network包中的MLPClassifier类。在数据准备完全的情况下,调用该算法,可以方便完成神经网络的建模与预测,程序的代码如下:

程序:神经网络手写数字识别

程序中让神经网络算法进行10 000次机器学习,程序的运行结果如下所示:

预测得分:1.0

预测值

[[0 0 0 0 0 0 1 0 0 0]

[0 0 0 0 1 0 0 0 0 0]

[0 0 1 0 0 0 0 0 0 0]

[0 0 1 0 0 0 0 0 0 0]

[0 0 0 0 0 0 0 0 1 0]

[0 0 0 1 0 0 0 0 0 0]]

真值

[[0.0.0.0.0.0.1.0.0.0.]

[0.0.0.0.1.0.0.0.0.0.]

[0.0.1.0.0.0.0.0.0.0.]

[0.0.1.0.0.0.0.0.0.0.]

[0.0.0.0.0.0.0.0.1.0.]

[0.0.0.1.0.0.0.0.0.0.]]

程序的运行结果表明,进行10 000次建模后,预测检验集的小数字是完全正确的。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈