Gif动图验证码识别

4,937 阅读3分钟

环境: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.分析验证码的生成规则,程序模拟生成类似样本作为训练样本

需要通用识别服务的留言邮箱地址即可,看到消息会发送程序到邮箱

敬畏法律,请勿做非法用途