上面已经到了切割字库和图片识别的阶段了,本篇博客只是吐槽一下自己探索图片识别的过程,都是试验失败的例子。
最开始的思路非常直接简单: 1、把字模的像素掉打印出来。每个字符宽度为5,高度为8,那么就是40个像素点的数据。
记录下来的一些特征数据点如下:
#0:2 6 9 16 26 29 37 38
#0:2 9 11 21 31 34 37
#1:2 6 12 22 32 37
#1:3 7 13 23 28
#1:1 5 11 21 31 36
#1:1 5 11 21 26 36
#2:2 9 19 23 27 36 37 39
#2:2 9 14 23 27 36 37 39
#2:0 7 12 21 25 36
#2:1 8 18 22 26 35 36 38
#2:2 9 19 23 31 36 38 39
#3:2 9 14 18 24 34 36 37
#3:1 8 13 17 23 33 35 36
#4:2 6 12 22 25 27 32
#4:4 8 14 17 21 24 26 29 34 39
#5:2 4 6 16 18 24 34 36 38
#5:1 3 5 15 17 23 33 35 37
#5:0 2 16 22 32 36
#6: 7 11 18 21 26 34 37
#6:2 6 10 17 20 28 30 37
#6:1 5 16 27 35 37
#6:1 8 18 22 26 35 36 38
#6:0 15 26 36
#7:0 2 8 18 22 31
#7:1 3 9 19 23 32
#7:1 7 17 21 30
#7:0 2 16 22 32 36
#8:2 6 9 14 17 21 23 31 34 37
#8:1 5 8 16 17 23 25 30 33 36
#9:2 5 13 15 19 21 28 33 36
#9:2 9 11 19 21 24 29 37 38
#9:1 8 10 18 20 23 28 36 37
#.:37
#0:2 6 9 16 26 29 37 38
#0:2 9 11 21 31 34 37
2、根据字符的特征点来判断是否是某个字符。简单判断示例如下。
def is7(data,total):
if total < 7:
if data[8] == 0 and data[18] == 0 and data[22] == 0 and data[31] == 0:
return True
if data[9] == 0 and data[19] == 0 and data[23] == 0 and data[32] == 0:
return True
if data[7] == 0 and data[17] == 0 and data[21] == 0 and data[30] == 0:
return True
return False
def pictonum(im):
#print '------pictonum()--------'
numstr = ''
single_width = 5
for index in xrange(5):
total = 0
box = (index*single_width,0,(index+1)*single_width,8)
newim = im.crop(box)
w, h = newim.size
data = list(newim.getdata())
#print data
for y in xrange(h):
for x in xrange(w):
if(data[y*w+x]) == 0:
#print y*w+x
total += 1
if is0(data,total):
numstr = '%s0' % numstr
elif is1(data,total):
numstr = '%s1' % numstr
elif is2(data,total):
numstr = '%s2' % numstr
elif is3(data,total):
numstr = '%s3' % numstr
elif is4(data,total):
numstr = '%s4' % numstr
elif is5(data,total):
numstr = '%s5' % numstr
elif is6(data,total):
numstr = '%s6' % numstr
elif is7(data,total):
numstr = '%s7' % numstr
elif is8(data,total):
numstr = '%s8' % numstr
elif is9(data,total):
numstr = '%s9' % numstr
elif isdot(data,total):
if not '.' in numstr:
numstr = '%s.' % numstr
elif index == 4:
pass
elif len(numstr) == 1:
if not '.' in numstr:
numstr = '%s.' % numstr
else:
pass
#print index
#print '?'
print numstr
return numstr
验证结果: 每张新图片(包含了10*5以上的数字),总有一些是因为特征点不一样而认不出来的。然后我又不得不记录新的特征点,然后作为特列加到判断中去。这么简单的图片,没有噪点没有干扰线没有扭曲,识别率达不到99%以上就是失败了。
两个方向思考:
-
预处理的图片没有做好: (1)一个数字有四五种不同的像素点阵,我觉得3种就差不多了。 (2)由于输出的数字并不是等宽的,我却按等宽的切割,导致图片切割不均匀,有的切少了,有的切多了,会形成误判。
-
有没有更方便的数学方法? 脑海里闪现过矩阵、行列式、矢量,我又搜索了不少的资料看,什么欧氏距离、汉明距离、神经网络、OCR识别(如tesseract,pytesser)等。
神经网络之类的不懂,我也觉得这么简单的数字,没有必要训练数据集。OCR,用别人的,似乎也要训练一下,否则识别率也不高。还是自己做吧。
我做过一些不是很成功的尝试: 汉明距离: 在信息论中,两个等长字符串之间的汉明距离是两个字符串对应位置的不同字符的个数。换句话说,它就是将一个字符串变换成另外一个字符串所需要替换的字符个数。 例如: * 1011101 与 1001001 之间的汉明距离是 2。 * 2143896 与 2233796 之间的汉明距离是 3。 * “toned” 与 “roses” 之间的汉明距离是 3。
1、就是参考汉明距离的思路,做一个标准的字库,识别时候将字和字库比较,汉明距离小于3的就认为是同一数字了。 2、由于那时候切割字的问题还没解决,如果判断不识别还不够,我还做了移位。一次识别不成功,我会移位一次进行第二次比较。 如1011101 和11011100比较,我会计算两个数字中第一个0出现的位置,位置相减获得偏移量。
试验结果:识别效率跟第一次做的差不多,也还需要添加各种特殊情况,放弃。
当然,还有一种方法可以继续尝试,那就是全部比较一次汉明距离,然后取最小的距离为识别的数字。我没有试这种思路,我觉得全部轮询耗时太多,二是如果出现距离一样的怎么办?
痛定思痛,我觉得方法无罪,主要是我图片预处理做的不够好。继续新的一轮探索,详看下篇分解。
...