用python加“验证码”为关键词在baidu里搜一下,可以找到很多关于验证码识别的文章。我大体看了一下,主要方法有几类:一类是通过对图片进行处理,然后利用字库特征匹配的方法,一类是图片处理后建立字符对应字典,还有一类是直接利用ocr模块进行识别。不管是用什么方法,都需要首先对图片进行处理,于是试着对下面的验证码进行分析。
一、图片处理
这个验证码中主要的影响因素是中间的曲线,首先考虑去掉图片中的曲线。考虑了两种算法:
第一种是首先取到曲线头的位置,即x=0时,黑点的位置。然后向后移动x的取值,观察每个x下黑点的位置,判断前后两个相邻黑点之间的距离,如果距离在一定范围内,可以基本判断该点是曲线上的点,最后将曲线上的点全部绘成白色。试了一下这种方法,结果得到的图片效果很一般,曲线不能完全去除,而且容量将字符的线条去除。
第二种考虑用单位面积内点的密度来进行计算。于是首先计算单位面积内点的个数,将单位面积内点个数少于某一指定数的面积去除,剩余的部分基本上就是验证码字符的部分。本例中,为了便于操作,取了5*5做为单位范围,并调整单位面积内点的标准密度为11。处理后的效果:
二、字符验证
这里我使用的方法是利用pytesser进行ocr识别,但由于这类验证码字符的不规则性,使得验证结果的准确性并不是很高。具体哪位大牛,有什么好的办法,希望能给指点一下。
三、准备工作与代码实例
1、PIL、pytesser、tesseract
(1)安装PIL:下载地址:http://www.pythonware.com/products/pil/
(2)pytesser:下载地址:http://code.google.com/p/pytesser/,下载解压后直接放在代码相同的文件夹下,即可使用。
(3)Tesseract OCR engine下载:http://code.google.com/p/tesseract-ocr/,下载后解压,找到tessdata文件夹,用其替换掉pytesser解压后的tessdata文件夹即可。
2、具体代码
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
42
43
44
45
46
47
48
49
|
#encoding=utf-8 ###利用点的密度计算 import Image,ImageEnhance,ImageFilter,ImageDraw import sys from pytesser import * #计算范围内点的个数 def numpoint(im): w,h = im.size data = list ( im.getdata() ) mumpoint = 0 for x in range (w): for y in range (h): if data[ y * w + x ] ! = 255 : #255是白色 mumpoint + = 1 return mumpoint #计算5*5范围内点的密度 def pointmidu(im): w,h = im.size p = [] for y in range ( 0 ,h, 5 ): for x in range ( 0 ,w, 5 ): box = (x,y, x + 5 ,y + 5 ) im1 = im.crop(box) a = numpoint(im1) if a< 11 : ##如果5*5范围内小于11个点,那么将该部分全部换为白色。 for i in range (x,x + 5 ): for j in range (y,y + 5 ): im.putpixel((i,j), 255 ) im.save(r 'img.jpg' ) def ocrend(): ##识别 image_name = "img.jpg" im = Image. open (image_name) im = im. filter (ImageFilter.MedianFilter()) enhancer = ImageEnhance.Contrast(im) im = enhancer.enhance( 2 ) im = im.convert( '1' ) im.save( "1.tif" ) print image_file_to_string( '1.tif' ) if __name__ = = '__main__' : image_name = "1.png" im = Image. open (image_name) im = im. filter (ImageFilter.DETAIL) im = im. filter (ImageFilter.MedianFilter()) enhancer = ImageEnhance.Contrast(im) im = enhancer.enhance( 2 ) im = im.convert( '1' ) ##a=remove_point(im) pointmidu(im) ocrend() |
本人的这个方法,最终识别率确实不高,写出来,哪位高手有好的思路或者做法,望不惜赐教!