首页 > 编程 > Python > 正文

python验证码识别教程之利用投影法、连通域法分割图片

2020-02-15 21:37:34
字体:
来源:转载
供稿:网友

前言

今天这篇文章主要记录一下如何切分验证码,用到的主要库就是Pillow和Linux下的图像处理工具GIMP。首先假设一个固定位置和宽度、无粘连、无干扰的例子学习一下如何使用Pillow来切割图片。

使用GIMP打开图片后,按 加号 放大图片,然后点击View->Show Grid来显示网格线:


其中,每个正方形边长为10像素,所以数字1切割坐标为左20、上20、右40、下70。以此类推可以知道剩下3个数字的切割位置。

代码如下:

from PIL import Imagep = Image.open("1.png")# 注意位置顺序为左、上、右、下cuts = [(20,20,40,70),(60,20,90,70),(100,10,130,60),(140,20,170,50)]for i,n in enumerate(cuts,1): temp = p.crop(n) # 调用crop函数进行切割 temp.save("cut%s.png" % i)

切割后得到4张图片:


那么,如果字符位置不固定怎么办呢?现在假设一种随机位置宽度、无粘连、无干扰线的情况。

第一种方法,也是最简单的方法叫做”投影法”。原理就是将二值化后的图片在竖直方向进行投影,根据投影后的极值来判断分割边界。这里我依然使用上面的验证码图片来进行演示:

def vertical(img): """传入二值化后的图片进行垂直投影""" pixdata = img.load() w,h = img.size ver_list = [] # 开始投影 for x in range(w): black = 0 for y in range(h):  if pixdata[x,y] == 0:  black += 1 ver_list.append(black) # 判断边界 l,r = 0,0 flag = False cuts = [] for i,count in enumerate(ver_list): # 阈值这里为0 if flag is False and count > 0:  l = i  flag = True if flag and count == 0:  r = i-1  flag = False  cuts.append((l,r)) return cutsp = Image.open('1.png')b_img = binarizing(p,200)v = vertical(b_img)

通过vertical函数我们就得到了一个包含所有黑色像素在X轴上投影后左右边界的位置。由于验证码没有任何干扰,所以我的阈值设定为0。 关于binarizing函数可以参考上一篇文章

输出如下:

[(21, 37), (62, 89), (100, 122), (146, 164)]

可以看到,投影法给出左右边界和我们手工查看得到很接近。对于上下边界,偷懒的可以直接使用0和图片的高度,也可以在水平方向进行投影,这里有兴趣的小伙伴可以自己尝试。

但是,对于字符间有粘连的情况,投影法就会出现拆分错误,比如上篇文章中的:


修改阈值为5后,投影法给出的左右边界是:

[(5, 27), (33, 53), (59, 108)]            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表