本帖最后由 lennydada 于 2020-7-9 23:21 编辑
于2020/7/1-3日编写,仅供个人学习参考,请勿用于非法途径。
验证码识别去干扰线 去噪点
字符分割算法用了垂直投影取中间前后4点比较进行分割
[Python] 纯文本查看 复制代码 # 需要用到的库
from itertools import groupby
from PIL import Image
import time
import requests
import re
首先下载验证码图片:
[Python] 纯文本查看 复制代码 def down_img(i):
# code地址
codeurl = 'https://nuc.api.mgtv.com/v1/LoginCaptcha?'
# code参数
codedata = {
'_support':'10000000',
'deviceid':'1e92894d-daac-497d-b4d9-25d41da0568e',
'appVersion':'pcweb-6.3.0.gray',
'dname':'',
'src':'intelmgtv',
'invoker':'pcweb',
'username':'@账号',
'smscode':'86',
't':'@时间戳',
}
t = int(round(time.time() * 1000))
codedata['username'] = '这里随便输个账号'
codedata['t'] = t
coderes = requests.get(codeurl,params=codedata)
with open(str(i)+'.png', 'wb') as file:
file.write(coderes.content)
file.close
这里用画图工具(去色工具)获取,也可以用其它图色处理工具
处理验证码图片:
观察验证码可以发现,干扰线为 FF0000 的红色
直接遍历图片像素把红色的点转换为白色,其它转为黑色
然后对字体进行一些小修补和去除杂点
[Python] 纯文本查看 复制代码 def change_img(img,i):
pixels = img.load()
for k in range(img.size[0]):
for j in range(img.size[1]):
if pixels[k,j] == (255, 0, 0):
pixels[k,j] = (255, 255, 255)
elif pixels[k,j] != (255, 255, 255):
pixels[k,j] = (0, 0, 0)
for k in range(1,img.size[0]-1):
for j in range(1,img.size[1]-1):
x1 = pixels[k-1,j]
x2 = pixels[k+1,j]
y1 = pixels[k,j-1]
y2 = pixels[k,j+1]
if pixels[k,j] == (255, 255, 255):
if x1 == x2 == y1 == y2 == (0, 0, 0):
pixels[k,j] = (0, 0, 0)
elif x1 == y1 == y2 == (0, 0, 0):
pixels[k,j] = (0, 0, 0)
elif x2 == y1 == y2 == (0, 0, 0):
pixels[k,j] = (0, 0, 0)
if pixels[k,j] == (0, 0, 0):
if x1 == x2 == y1 == y2 == (255, 255, 255):
pixels[k,j] = (255, 255, 255)
elif x1 == x2 == y1 == (255, 255, 255):
pixels[k,j] = (255, 255, 255)
elif x1 == x2 == y2 == (255, 255, 255):
pixels[k,j] = (255, 255, 255)
elif x1 == y1 == y2 == (255, 255, 255):
pixels[k,j] = (255, 255, 255)
elif x2 == y1 == y2 == (255, 255, 255):
pixels[k,j] = (255, 255, 255)
img.save(str(i)+'_new.png')
对验证码进行分割处理:
先对验证码进行简单处理边缘白色无用像素,便于后面切割
[Python] 纯文本查看 复制代码 def cut_LR(img):
pixels = img.load()
x,y = img.size
for w in range(x):
for h in range(y):
if pixels[w,h] == 0:
x1 = w
break
if pixels[w,h] == 0:
break
for w in range(x):
w = x - w - 1
for h in range(y):
if pixels[w,h] == 0:
x2 = w + 1
break
if pixels[w,h] == 0:
break
for h in range(y):
for w in range(x1,x2):
if pixels[w,h] == 0:
y1 = h
break
if pixels[w,h] == 0:
break
for h in range(y):
h = y - h - 1
for w in range(x1,x2):
if pixels[w,h] == 0:
y2 = h + 1
break
if pixels[w,h] == 0:
break
return x1,y1,x2,y2
传入处理后的图片进行垂直投影
[Python] 纯文本查看 复制代码 def vertical(img):
pixdata = img.load()
w,h = img.size
result = []
for x in range(w):
black = 0
for y in range(h):
if pixdata[x,y] == 0:
black += 1
result.append(black)
return result
对垂直投影结果进行处理,取投影结果中间前后取4个值对比,
在其中取最小值第一次进行分割(变成2+2的两个验证码)
然后再对其二次分割成(1+1+1+1)的验证码
[Python] 纯文本查看 复制代码 def get_start_x(hist_width):
mid = len(hist_width) // 2
temp = hist_width[mid-4:mid+5]
return mid - 4 + temp.index(min(temp))
def get_split(img,hist_width):
w,h = img.size
box1 = (0,0,hist_width,h)
box2 = (hist_width,0,w,h)
img_1 = img.crop(box1)
img_chuizhi = vertical(img_1)
split_x1 = get_start_x(img_chuizhi)
w1,h1 = img_1.size
box_1 = (0,0,split_x1,h1)
box_2 = (split_x1,0,w1,h1)
img_1.crop(box_1).save('x_1.png')
img_1.crop(box_2).save('x_2.png')
img_2 = img.crop(box2)
img_chuizhi = vertical(img_2)
split_x2 = get_start_x(img_chuizhi)
w2,h2 = img_2.size
box_3 = (0,0,split_x2,h2)
box_4 = (split_x2,0,w2,h2)
img_2.crop(box_3).save('x_3.png')
img_2.crop(box_4).save('x_4.png')
最终处理结果:
分割效果还是很不错的,少许粘连,少许倾斜用这种垂直投影的切割方法处理出来的效果已经可以达到不错的效果,可完美分割99%。为后续训练节省不少时间。
代码比较乱,因为这是初稿(主要是刚学py没多久,之前都是用易语言比较多,规范的问题就一略而过了,哈哈),写的没那么规范。
如果有看不懂的可以留言。
这种验证码比较简单,粘连倾斜的比较少,所以比较简单。如果是倾斜比较厉害的可以用水滴算法进行分割。
吾爱论坛ID:lennydada
如果觉得对你有帮助请给个评分哦,每日评分都是免费的 |