环境:python3.7
本文识别验证码如下图所示:
识别流程:
流程说明:
1.Gif转png,每一帧保存为png格式图片 2.每张png图片进行单独识别 3.统计每个对应位置字符频率,每个位置取最高频率字符作为对应位置字符识别结果 4.拼接指定长度字符作为最终识别结果
抽帧模块:
def gif_to_png(length,image):
'''
gif抽帧
:param length:
:param image:
:return:
'''
try:
yzm_list = []
for i in range(1, length):
image.seek(i)
stream = BytesIO()
image.save(stream, 'PNG')
s = stream.getvalue()
yzm_list.append(s)
return yzm_list
except Exception as e:
print(e)
return None
Gif转变成多张图片如下图:
识别模块:
def recogition(yzm_data):
'''
验证码识别
:param yzm_data:
:return:
'''
resp = requests.post('http://127.0.0.1:8080', data=yzm_data)
return resp.text
每一帧图片对应识别结果:
文件命名规则:序号_识别结果.png 例如:1_qfd2a.png对应1.png
图片识别结果,识别结果为"qfd2a"
识别模块使用的是训练好的统用识别模型,基于深度学习训练验证码识别模型,网上有很多资料。自处不在赘述。就是你自己需要有一个图片识别工具,传入图片识别出字符即可。 如有需要我程序中使用的识别程序,可以留言给我邮箱弟子,看到后会把识别程序发到邮箱
词频计算模块
def get_max_char(str):
'''
获取频率最高字符
:param str:
:return:
'''
count = Counter(str)
count_list = list(count.values())
max_value = max(count_list)
max_list = []
for k, v in count.items():
if v == max_value:
max_list.append(k)
return max_list[0]
可能会有多个字符出现次数一样,默认取第一个,也可以按照字母表排序之后取第一个,本文取第一个出现的即可。
识别结果:
qfd2
完整代码:
# -*- coding: utf-8 -*-
# @Software: PyCharm
import requests
import time
import json
from PIL import Image
from io import BytesIO
from collections import Counter
def get_max_char(str):
'''
获取频率最高字符
:param str:
:return:
'''
count = Counter(str)
count_list = list(count.values())
max_value = max(count_list)
max_list = []
for k, v in count.items():
if v == max_value:
max_list.append(k)
return max_list[0]
def recogition(yzm_data):
'''
验证码识别
:param yzm_data:
:return:
'''
resp = requests.post('http://127.0.0.1:8080', data=yzm_data)
return resp.text
def img_to_text(yzmdatas):
'''
图片转字符
:param length:
:return:
'''
yzm1 = ""
yzm2 = ""
yzm3 = ""
yzm4 = ""
for data in yzmdatas:
text = recogition(data)
json_obj = json.loads(text)
yzm_text = json_obj.get("code","")
#本文中的验证码长度为4 实际测试中只要长度大于等于4的都可以统计进去,不影响识别准确率
if len(yzm_text) == 4:
l_yzm = list(yzm_text)
yzm1 = yzm1 + l_yzm[0]
yzm2 = yzm2 + l_yzm[1]
yzm3 = yzm3 + l_yzm[2]
yzm4 = yzm4 + l_yzm[3]
yzm1 = get_max_char(yzm1)
yzm2 = get_max_char(yzm2)
yzm3 = get_max_char(yzm3)
yzm4 = get_max_char(yzm4)
return yzm1+yzm2+yzm3+yzm4
def download():
'''
下载验证码
:return:
'''
#验证码地址
url = 'http://credit.customs.gov.cn/ccppserver/verifyCode/creator'
resp = requests.get(url)
data = resp.content
return data
def gif_to_png(length,image):
'''
gif抽帧
:param length:
:param image:
:return:
'''
try:
yzm_list = []
for i in range(1, length):
image.seek(i)
stream = BytesIO()
image.save(stream, 'PNG')
s = stream.getvalue()
yzm_list.append(s)
return yzm_list
except Exception as e:
print(e)
return None
def handle_yzm(length):
'''
处理验证码
:return:
'''
gif = download()
start = time.time()
if gif:
data = BytesIO(gif)
image = Image.open(data)
png_list = gif_to_png(length, image)
if png_list:
yzm_text = img_to_text(png_list)
with open("./Gif_IMG/{}_{}.gif".format(yzm_text, str(time.time())),"wb") as fw:
fw.write(gif)
end = time.time()
print("抽帧length:{}-花费时间:{}".format(length, end - start))
def run():
#抽帧长度:具体抽帧多少可以依据实际的gif识别准确率来调整。
#抽帧越少识别率可能会低,但是识别所需的时间会减少。23帧准确率98%,时间1s; 6帧准确率85%,时间0.5s左右
#在识别速度和精度之间找一个平衡点即可
length = 10
#识别图片个数
num = 20
for i in range(num):
handle_yzm(length)
if __name__ == '__main__':
run()
总结
gif识别和png、jpg格式图片识别思路一直,甚至视频验证码识别也可以借鉴Gif识别思路。验证码识别的核心还是识别模型的训练;而要训练一个识别率高,且支持各种长度、各种尺寸图片识别模型,则需要的训练样本就会很多。但是针对单一类型验证码来说,1万多张样本就可以得到一个识别率90%以上的识别模型。
训练样本获取:
1.借助打码平台
2.分析验证码的生成规则,程序模拟生成类似样本作为训练样本
完
需要通用识别服务的留言邮箱地址即可,看到消息会发送程序到邮箱
敬畏法律,请勿做非法用途