首页 > 代码库 > 用BP人工神经网络识别手写数字
用BP人工神经网络识别手写数字
http://wenku.baidu.com/link?url=HQ-5tZCXBQ3uwPZQECHkMCtursKIpglboBHq416N-q2WZupkNNH3Gv4vtEHyPULezDb50ZcKor41PEikwv5TfTqwrsQ4-9wmH06L7bYD04u
用BP人工神经网络识别手写数字
赖勇浩(
http://laiyonghao.com
)
这是我读工程硕士的时候完成课程作业时做的,
放在
dropbox
的角落中生尘已经有若干年
头了,
最近
@shugelee
同学突然来了兴致搞验证码识别,
问到我的时候我记起自己做过一
点点东西,特发上来给他参考,并趁机补充了一下《
Python
也可以》系列。
图像预处理
使用下图(后方称为
SAMPLE_BMP
)作为训练和测试数据来源,
下文将讲述如何将图像转换为训练数据。
灰度化和二值化
在字符识别的过程中,
识别算法不需要关心图像的彩色信息。
因此,
需要将彩色图像转化为
灰度图像。
经过灰度化处理后的图像中还包含有背景信息。
因此,我们还得进一步处理,
将
背景噪声屏蔽掉,
突显出字符轮廓信息。
二值化处理就能够将其中的字符显现出来,
并将背
景去除掉。在一个
[0
,
255]
灰度级的灰度图像中,我们取
196
为该灰度图像的归一化值,
代码如下:
[python]
view plaincopy
1.
def
convert_to_bw(im):
2.
im = im.convert("L")
3.
im.save("sample_L.bmp")
4.
im = im.point(
lambda
x: WHITE
if
x > 196
else
BLACK)
5.
im = im.convert(‘1‘)
6.
im.save("sample_1.bmp")
7.
return
im
下图是灰度化的图像,可以看到背景仍然比较明显,有一层淡灰色:
下图是二值化的图像,可以看到背景已经完全去除:
图片的分割和规范化:
通过二值化图像,
我们可以分割出每一个字符为一个单独的图片,
然后再计算相应的特征值,
如下图所示:
这些图片是由程序自动进行分割而成,其中用到的代码片段如下:
[python]
view plaincopy
1.
def
split(im):
2.
assert
im.mode == ‘1‘
3.
result = []
4.
w, h = im.size
5.
data = im.load()
6.
xs = [0, 23, 57, 77, 106, 135, 159, 179, 205, 228, w]
7.
ys = [0, 22, 60, 97, 150, h]
8.
for
i, x
in
enumerate(xs):
9.
if
i + 1 >= len(xs):
10.
break
11.
for
j, y
in
enumerate(ys):
12.
if
j + 1 >= len(ys):
13.
break
14.
box = (x, y, xs[i+1], ys[j+1])
15.
t = im.crop(box).copy()
16.
box = box + ((i + 1) % 10, )
17.
# save_32_32(t, ‘num_%d_%d_%d_%d_%d‘%box)
18.
result.append((normalize_32_32(t, ‘num_%d_%d_%d_%d_%d‘%box), (i + 1) % 10)
)
19.
return
result
其中的
xs
和
ys
分别是横向和竖向切割的分界点,由手工测试后指定,
t =
im.crop(box).copy()
代码行是从指定的区域中
“抠”
出图片,
然后通过
normalize_32_32
进行规范化。
进行规范化是为了产生规则的训练和测试数据集,
也是为了更容易地地计算出
特征码。
产生训练数据集和测试数据集
为简单起见,我们使用了最简单的图像特征——黑色像素在图像中的分布来进行训练和测
试。
首先,
我们把图像规范化为
32*32
像素的图片,
然后按
2*2
分切成
16*16
共
256
个
子区域,
然后统计这
4
个像素中黑色像素的个数,
组成
256
维的特征矢量,
如下是数字
2
的一个特征矢量:
0 0 4 4 4 2 0 0 0 0 0 0 0 0 2 4 0 0 4 4 4 2 0 0 0 0 0 0 0 0 2 4 2 2 4 4 2 1 0 0 0 0 0 0 1 2
3 4 4 4 4 4 0 0 0 0 0 0 0 0 2 4 4 4 4 4 4 4 0 0 0 0 0 0 0 0 2 4 4 4 4 4 0 0 0 0 0 0 0 0 0 0
2 4 4 4 4 4 0 0 0 0 0 0 0 0 0 0 2 4 4 4 4 4 0 0 0 0 0 0 0 4 4 4 4 4 4 4 4 4 0 0 0 0 0 0 0 4
4 4 4 4 4 4 4 4 2 2 2 2 2 2 2 4 4 2 3 4 4 4 4 4 4 4 4 4 4 4 4 4 4 0 2 4 4 4 2 2 2 2 4 3 2 2
2 2 2 0 2 4 4 4 0 0 0 0 4 2 0 0 0 0 0 0 2 4 4 4 0 0 0 0 4 2 0 0 0 0 0 0 2 4 4 4 0 0 0 0 0 0
0 0 0 0 0 0 2 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0 2 4 4 4
相应地,因为我们只需要识别
0~9
共
10
个数字,所以创建一个
10
维的矢量作为结果,
数字相应的维置为
1
值,其它值为
0
。数字
2
的结果如下:
0 0 1 0 0 0 0 0 0 0
我们特征矢量和结果矢量通过以下代码计算出来后,按
FANN
的格式把它们存到
train.data
中去:
[python]
view plaincopy
1.
f = open(‘train.data‘, ‘wt‘)
2.
>>f, len(result), 256, 10
3.
for
input, output
in
result:
4.
>>f, input
5.
>>f, output
BP
神经网络
利用神经网络识别字符是本文的另外一个关键阶段,良好的网络
性能是识别结果可靠性的重要保证。
这里就介绍如何利用
BP
神经网络来识别字符。
反向传
播网络(即:
Back-Propagation Networks ,
简称:
BP
网络)是对非线性可微分函数进行
权值训练的多层前向网络。在人工神经网络的实际应用中,
80%
~
90%
的模型采用
BP
网
络。它主要用在函数逼近,模式识别,分类,数据压缩等几个方面,体现了人工神经网络的
核心部分。
网络结构
网络结构的设计是根据输入结点和输出结点的个数和网络性能来决定的,
如下图。
本实验中
的标准待识别字符的大小为
32*32
的二值图像,即将
1024
个像素点的图像转化为一个
256
维的列向量作为输入。由于本实验要识别出
10
个字符,可以将目标输出的值设定为
一个
10
维的列向量,其中与字符相对应那个位为
1
,其他的全为
0
。根据实际经验和试
验确定,本文中的网络隐含层结点数目为
64
。因此,本文中的
BP
网络的结构为
256-64-10
。
用BP人工神经网络识别手写数字