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

matlab投影法分割图像_python验证码识别教程之利⽤投影
法、连通域法分割图⽚
这篇⽂章主要介绍了关于python验证码识别教程之利⽤投影法、连通域法分割图⽚,有着⼀定的参考价值,现在分享给⼤家,有需要的朋友可以参考⼀下
前⾔按摩毯
今天这篇⽂章主要记录⼀下如何切分验证码,⽤到的主要库就是Pillow和Linux下的图像处理⼯具GIMP。⾸先假设⼀个固定位置和宽度、⽆粘连、⽆⼲扰的例⼦学习⼀下如何使⽤Pillow来切割图⽚。
使⽤GIMP打开图⽚后,按 加号 放⼤图⽚,然后点击View->Show Grid来显⽰⽹格线:
其中,每个正⽅形边长为10像素,所以数字1切割坐标为左20、上20、右40、下70。以此类推可以知道剩下3个数字的切割位置。
代码如下:
from PIL import Image
p = 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 cuts
p = 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)]
明显最后的6和9数字没有切割。
修改阈值为7,结果则是:
[(5, 27), (33, 53), (60, 79), (83, 108)]
所以对于简单粘连的情况,调整阈值也是可以解决的。
第⼆种⽅法,叫做CFS连通域分割法。原理就是假定每个字符都由⼀个单独的连通域组成,换⾔之就是⽆粘连,到⼀个⿊⾊像素并开始判断,直到所有相连的⿊⾊像素都被遍历标记过后即可判断出这个字符的分割位置。算法如下:
将⼆值化后的图⽚进⾏从左到右、从上到下的遍历,如果遇到⿊⾊像素并且这个像素没有没访问过,就将这个像素⼊栈并标记为已经访问。洗水
如果栈不为空,则继续探测周围8个像素,并执⾏第2步;如果栈空,则代表探测完了⼀个字符块。
探测结束,这样就确定了若⼲字符。
代码如下:
import queue
def cfs(img):
"""传⼊⼆值化后的图⽚进⾏连通域分割"""
pixdata = img.load()
w,h = img.size
visited = set()
q = queue.Queue()
offset = [(-1,-1),(0,-1),(1,-1),(-1,0),(1,0),(-1,1),(0,1),(1,1)]
cuts = []
for x in range(w):
for y in range(h):
x_axis = []
#y_axis = []
if pixdata[x,y] == 0 and (x,y) not in visited:
q.put((x,y))
visited.add((x,y))
while pty():
x_p,y_p = q.get()
for x_offset,y_offset in offset:
x_c,y_c = x_p+x_offset,y_p+y_offset
if (x_c,y_c) in visited:
continue
visited.add((x_c,y_c))
try:
脂肪酸酰胺
if pixdata[x_c,y_c] == 0:
q.put((x_c,y_c))
x_axis.append(x_c)
#y_axis.append(y_c)
except:
yig滤波器pass
if x_axis:threadx操作系统
min_x,max_x = min(x_axis),max(x_axis)
if max_x - min_x > 3:
分子筛柱# 宽度⼩于3的认为是噪点,根据需要修改
cuts.append((min_x,max_x))
return cuts
调⽤后输出结果和使⽤投影法是⼀样的。另外我看⽹上还有⼀种叫做“泛洪填充(Flood Fill)”的⽅法,似乎和连通域是⼀样的。相关推荐:
python验证码识别教程之灰度处理、⼆值化、降噪与tesserocr识别

本文发布于:2024-09-22 20:35:22,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/3/219089.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:投影   位置   像素
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议