验证码识别之智能切割字符

前面一篇文章讲过了关于验证码的一些简单的识别技术(验证码识别入门

其中一个很大的局限性,就是我的字符分割是根据我事先在图片上量取的尺寸,换句话说,加入同样的代码换个图片来源就会出错,更不谈位置不规则的验证码。

后来找了一些资料,实现了智能切割字符,可以实现自动识别字符的位置,对位置不规则的尤其有效。下面一点点的来分析这个实现。

比如这个验证码:
1

可能看不是很清楚,简单二值去噪点,然后放大后:
2

各个字符的位置都是不确定的,但是我们来分析下横轴上的像素点分布,利用一段python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
img=Image.open(dir+'3.jpg')
#初始化一个数组,统计横轴上每处的像素点数
flagx=[0 for x in range(img.size[0])]
pix=img.load()
#横坐标上的像素分布
for x in range(img.size[0]):
for y in range(img.size[1]):
if pix[x,y][0]<90:
flagx[x]+=1
print flagx


```>[0, 0, 0, 0, 0, 1, 1, 3, 3, 4, 6, 6, 4, 5, 5, 5, 5, 4, 7, 7, 17, 24, 25, 25, 20, 13, 6, 2, 0, 1, 1, 3, 12, 21, 12, 9, 8, 8, 7, 7, 7, 7, 8, 9, 9, 10, 10, 19, 21, 6, 0, 0, 0, 0, 6, 9, 15, 14, 8, 3, 5, 9, 13, 15, 13, 8, 0, 0, 0, 0, 3, 4, 4, 5, 5, 7, 17, 19, 19, 18, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

也就是从左到右每列上的像素点分别为0,0.......那么我们关注两个地方分别是0->n和n->0的地方,比如从左往右发现第5个开始不是0,28开始又变成0,我们很容易分析地一个字母的横坐标为5-28,然后用同样的方法,针对5-28的横坐标在纵坐标上取出像素分布:


>[0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 5, 6, 7, 8, 7, 7, 7, 7, 7, 7, 11, 15, 11, 8, 8, 9, 11, 11, 10, 7, 9, 6, 3, 0, 0, 0, 0, 0, 0, 0]

这样可以分析第一个字母的纵坐标为8-34。代码实现是这样的:

```python
for i in range(img.size[0]):
if flagx[i]>0 and flagx[i-1]<=0:
tmp=i#记录0->n的坐标
if flagx[i]>0 and flagx[i+1]<=0:
#完成一个字符的横坐标扫描,针对这段用同样的方法扫描纵坐标
flagy=[0 for x in range(img.size[1])]
for y in range(img.size[1]):
for x in range(i+1)[tmp:]:
if pix[x,y][0]<90:
flagy[y]+=1
#用flagy记录纵坐标像素分布
for j in range(img.size[1]):
if flagy[j]>0 and flagy[j-1]<=0:
ttmp=j#记录0->n的点
if flagy[j]>0 and flagy[j+1]<=0:
result.append([tmp,i,ttmp+1,j+1])
print result


[[5, 28, 8, 34], [29, 50, 3, 26], [54, 66, 11, 29], [70, 83, 12, 31]]

这就是四个字符的坐标,然后把这些坐标来切割图像字符就能很好的抠出来了,我的结果是这样的

3