一般的步骤就是上面这些,总的来说分为三部分,去除背景,分割字符,识别。
去除背景可以通过灰度化,二值化,去噪,倾斜度校正等(一般来说灰度化和二值化都是需要的,去噪和倾斜度看情况)
安装PIL工具,下载的地址是:http://www.pythonware.com/products/pil/,pytesser的使用需要PIL库的支持。
接着下载pytesser,下载的地址是:http://code.google.com/p/pytesser/downloads/list
由于code.google.com网站关闭了,所以,只能在csdn上下载了。下面是csdn的下载网址:http://download.csdn.net/download/pyliang_2008/5564135
最后,安装pytesser :
1、解压pytesser ,将解压后的文件复制到Python安装目录的Libsite-packages下,直接使用,比如我的安装目录是:C:Python27Libsite-packages。
文件名改成pytesser
2、把2个目录添加到环境变量之中。
C:Python27Libsite-packages
C:Python27Libsite-packagespytesser
3、还要在C:Python27Libsite-packages下面添加.pth 文件(pytesser.pth),这个文件里面,只有 “pytesser”字符串。
完成以上步骤之后,就可以编写图片文本识别的Python脚本了。参考脚本如下:
打开“运行”–cmd,键入“Python”后,进入Python命令交互模式,输入下面的代码:
from pytesser import * import ImageEnhance image = Image.open('D:\xiehao\workspace\python\5.png') #转化成灰度图 imgry = image.convert('L') #通过阈值来分割 threshold = 140 table = [] for i in range(256): if i < threshold: table.append(0) else: table.append(1) #二值化 out = imgry.point(table, '1') #另一种二值化方式不推荐 img = image.open() width, height = img.size num = [[img.load()[x, y] for y in range(0, height)] for x in range(0, width)] img = Image.new('RGB', (width, height), (255, 255, 255)) draw = ImageDraw.Draw(img) for x in range(width): for y in range(height): if num[x][y] < 140: draw.point((x, y), fill=(0,0,0)) else: draw.point((x, y), fill=(255,255,255)) #使用ImageEnhance可以增强图片的识别率 enhancer = ImageEnhance.Contrast(image) image_enhancer = enhancer.enhance(4) print image_to_string(image_enhancer)
分割字符串有多种方法
垂直像素直方图,假如图片宽度为100像素,则把图片切割为100个1像素的竖线,下面的红色部分为当前x坐标上所有黑色像素的总和。这么一来可以很容易的通过直方图的波峰波谷把4个字母分割开。
#图片切割算法
#垂直像素直方图,同一列有四个以上的黑块就记录x作为切割的左分界线,大于x的列中如果出现同一列黑块数目小于4就记录x作为切割的右分界线,该算法只适用于部分验证码。
def cut_img(image, startwidth, endwidth, startheight, endheight, cutwidth): split_x, split_y = [], [] for x in range(startwidth, endwidth): black_number = 0 for y in range(startheight, endheight): if image.load()[x, y] == 0: black_number += 1 if not split_x and black_number >= cut split_x.append(x) black_number = 0 if split_x and x - split_x[0] >= 8 and black_number < cut split_x.append(x) break for j in range(startheight, endheight): black_number = 0 for i in range(startwidth, endwidth): if image.load()[i, j] == 0: black_number += 1 if not split_y and black_number >= cut split_y.append(j) black_number = 0 if split_y and j - split_y[0] >= 8 and black_number < cut split_y.append(j) break # print split_x, split_y return (split_x[0], split_y[0], split_x[1], split_y[1]) image = open('xxx.jpg') #灰值化,二值化去噪处理 img = xxx(image) width,height = image.size box = [0, width, 0, height] for i in range(0, 4): box = cut_img(img, box[2], width, 0, height, cutwidth=4) print box # #切割 captcha_one = img.crop(box) captcha_one.show() print image_to_string(captcha_one)
#平均分割法
def cut_img_avg(image, startwidth, endwidth, startheight, endheight): split_x, split_y = [],[] for i in range(startwidth, endwidth): write_block = 0 for j in range(startheight, endheight): if image.load()[i, j] == 1: write_block += 1 elif not split_x and image.load()[i, j] == 0: split_x.append(i) break if write_block == endheight and split_x and i-split_x[0]>=40: split_x.append(i) break for y in range(startheight, endheight): write_block = 0 for x in range(startwidth, endwidth): if image.load()[x, y] == 1: write_block += 1 elif not split_y and image.load()[x, y] == 0: split_y.append(y) break if write_block == endwidth and split_y and y-split_y[0]>=10: split_y.append(y) break print split_x, split_y return (split_x[0], split_y[0], split_x[1], split_y[1]) image = open('xxx.jpg') #灰值化,二值化去噪处理 img = xxx(image) width,height = image.size box = cut_img_avg(img, 0, width, 0, height) for i in range(1, 5): avg = (box[2]-box[0])/4 abox = [box[0]+(i-1)*avg,box[1],box[0]+i*avg,box[3]] print abox capcha_two = img.crop(abox) capcha_two.show()
归一化
标准化
标准化的意思是指对于同一个字符,尽可能让每次识别前的样本都一致,以提高识别率。而验证码设计者则会用随机旋转,随机扭曲还有随机字体大小的方式防止字符被简单方法识别。
还原随机旋转的字符一般采用的是旋转卡壳算法:
此算法非常简单,对一张图片左右各旋转30度的范围,每次1度,旋转后用扫描线法判断字符的宽度,对于标准的长方形字体,在完全垂直的时候肯定是宽度最窄的。嗯?纳尼?上面的图是中间的最窄?好像的确是这样,不过只要每次旋转后的结果都一样,对于识别率不会有影响。
扭曲还原的算法比较蛋疼,效果也不怎么样(其实我不会),不过如果识别算法好的话,对扭曲的字符只要人能认出来,识别率也可以达到接近人类的水准。
还有一些常用到的算法,对于提高识别率和减少样本数量有一定帮助:
骨架细化:腐蚀算法
腐蚀算法的原理有点像剥洋葱,从最外层沿着最外面的一层像素一圈一圈的去掉,直到里面只剩下一层像素为止。腐蚀算法里面需要用到另一个算法,叫做凸包算法,用来找一堆像素点里面最外围的一层。
最后就是把字符变成统一大小,一般而言是把全部字符都缩到和验证码里出现过的最小的字符一个大小。
详情请自行google……
参考
http://blog.csdn.net/lanfan_11/article/details/45558573
http://www.360doc.com/content/16/0404/20/21340737_547844565.shtml