http://wenku.baidu.com/link?url=HQ-5tZCXBQ3uwPZQECHkMCtursKIpglboBHq416N-q2WZupkNNH3Gv4vtEHyPULezDb50ZcKor41PEikwv5TfTqwrsQ4-9wmH06L7bYD04u

用BP人工神经网络识别手写数字

yzw20091201上传于2013-01-31|暂无评价|356人阅读|13次下载|暂无简介|举报文档

   在手机打开
 

赖勇浩(

 

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.

print

>>f, len(result), 256, 10

3.

for

input, output

in

result:

4.

print

>>f, input

5.

print

>>f, output

BP

神经网络

利用神经网络识别字符是本文的另外一个关键阶段,良好的网络

性能是识别结果可靠性的重要保证。

这里就介绍如何利用

BP

神经网络来识别字符。

反向传

播网络(即:

Back-Propagation Networks ,

简称:

BP

网络)是对非线性可微分函数进行

权值训练的多层前向网络。在人工神经网络的实际应用中,

80%

90%

的模型采用

BP

络。它主要用在函数逼近,模式识别,分类,数据压缩等几个方面,体现了人工神经网络的

核心部分。

网络结构

网络结构的设计是根据输入结点和输出结点的个数和网络性能来决定的,

如下图。

本实验中

的标准待识别字符的大小为

32*32

的二值图像,即将

1024

个像素点的图像转化为一个

256

维的列向量作为输入。由于本实验要识别出

10

个字符,可以将目标输出的值设定为

一个

10

维的列向量,其中与字符相对应那个位为

1

,其他的全为

0

。根据实际经验和试

验确定,本文中的网络隐含层结点数目为

64

。因此,本文中的

BP

网络的结构为

256-64-10

 
 
 
04-26 22:57