利用神经网络识别12306验证码—(六)模型应用以及12306实战测试

article/2025/9/10 16:02:37

模型训练好之后,就可以应用于新图片的预测了。比如现在有下面这么一张12306的验证码,预测工作也分为两部分:上半部分的文字预测、下半部分的图片预测,将两部分划分开之后分别加载各自的模型进行预测。
在这里插入图片描述
文字预测:需要把文字部分从整个验证码图片中截取下来,截取函数在前面的文章中已介绍过,可以把截取函数保存为一个python文件,在这里直接导入即可。
图片预测:先把8个小图片分别截取保存下来,这些数据可以用作新模型训练的数据来源噢。用当前的模型对新数据预测并分类存储,然后利用新数据去改善旧数据的质量和数量,这样也可以提高模型的精度。
代码如下

import os, io
import json
import hashlib
import numpy as np
from PIL import Image
import tensorflow as tf
from collections import defaultdict
from tensorflow.keras import models
from collections import defaultdict
from split_text import judge_image_bk, split_image_text	#文本截取#在训练的时候对数据做了一些处理工作,所以在测试的时候也需要做相应的处理
def transform_test(feature, flag):feature = np.array(feature)[:, :, 0:3]	#图片格式转换feature = tf.image.resize(feature, [64, 64])feature = tf.divide(feature, 255.)mean = tf.convert_to_tensor([0.485, 0.456, 0.406])std = tf.convert_to_tensor([0.229, 0.224, 0.225])feature = tf.divide(tf.subtract(feature, mean), std)if flag == 1:   #训练时,只对文字部分做了标准化处理feature = tf.image.per_image_standardization(feature)return tf.image.convert_image_dtype(feature, tf.float32)#划分下面8张小验证码图片
def split_image(raw_image, image_shape):crop_area = [(5, 41, 71, 107), (77, 41, 143, 107), (149, 41, 215, 107), (221, 41, 287, 107),(5, 113, 71, 179), (77, 113, 143, 179), (149, 113, 215, 179), (221, 113, 287, 179)]if isinstance(raw_image, str):try:raw_image = Image.open(raw_image)lst = [raw_image.crop(region).resize(image_shape) for region in crop_area]except Exception as e:print('图片文件错误:', e.args)return Falsereturn lst#加载模型
def model_load(model_path):return models.load_model(model_path)#文本预测,返回预测结果以及图片数据
def text_predict(captcha_path):mode = judge_image_bk(captcha_path)# 把split_image_text函数的最后两行注释掉,然后添加return text;同时去掉name、save_dir两个参数imgs = split_image_text(captcha_path, (64, 64), mode)if not imgs:return text_predict(captcha_path)res_text = []for img in imgs:index = np.argmax(text_model.predict(np.expand_dims(transform_test(img, 1), 0))[0])res_text.append(dic[labels[index]])print('文字识别结果:', ' '.join(res_text))return res_text, imgs#图片预测,返回预测结果以及图片数据
def pic_predict(captcha_path):imgs = split_image(captcha_path, (64, 64))pred_res = []if imgs:res_dic = defaultdict(list)for j in range(1, 9):index = np.argmax(model_pic.predict(np.expand_dims(transform_test(imgs[j-1], 2), 0))[0])tmp = dic[labels[index]]res_dic[tmp].append(j)pred_res.append(tmp)res_dic = dict(res_dic)print('图片识别结果:', res_dic)return res_dic, pred_res, imgsreturn#匹配确定验证码的位置
def captcha_pos(res_text, res_pic):res = []for each in res_text:#挂钟和钟表这两个验证码事实上没啥区别,我试了很多次,只要出现表,全选完事if each == '挂钟' or each == '钟表':if res_pic.get('挂钟'):res.extend(res_pic.get('挂钟'))if res_pic.get('钟表'):res.extend(res_pic.get('钟表'))else:try:res.extend(res_pic.get(each))except:print(each + '无匹配图片!')res = list(set(res))	#去重print('验证码位置:', res)return res#创建文件夹
def mk_dir(path):try:os.mkdir(path)except FileExistsError:pass#保存文本图片和图像图片,如有需要
def save(save_dir, prediction, imgs):byter = io.BytesIO()  #创建字节流对象length = len(imgs)for i in range(length):save_path = os.path.join(os.getcwd(), save_dir, prediction[i])mk_dir(save_path)imgs[i].save(byter, format='JPEG')  #将JPEG格式转换成字节流格式#python提供的hashlib只接受字节流输入,获取图片的哈希值,方便对其命名imgs[i].save(os.path.join(save_path, hashlib.md5(byter.getvalue()).hexdigest() + '.jpg'))if length < 8:print('%d张文本图片保存成功!' % length)else:print('%d张图像图片保存成功!' % length)

以上是预测时的函数定义部分。
下面就可以定义相关参数,然后识别验证码。

if __name__ == '__main__':text_save_dir = 'text_prediction'pic_save_dir = 'pic_prediction'#第一次运行时,将创建两个文件夹mk_dir(text_save_dir)mk_dir(pic_save_dir)#加载两个模型text_model = model_load('text_model.h5')model_pic = model_load('pic_model.h5')#标签labels = ['Ants', 'Bandaid', 'Banner', 'Basketball', 'Beer', 'Boots', 'Bottleopener', 'Buscard', 'Candlestick', 'Cherry', 'Chineseknot', 'Coral', 'Cottonswab', 'Dashboard', 'DragonBoat', 'Earplugs', 'Electronicscale', 'Embroidery', 'Exhaustfan', 'Filebag', 'Flyswatter', 'Frenchfries', 'Gong', 'Jujube', 'MemorialGateway', 'Mop', 'Mungbean', 'Palmprint', 'Pyramid', 'Redbean', 'Refrigerator', 'Seagull', 'Seaweed', 'Spatula', 'Tapemeasure', 'Teacup', 'Tennisracket', 'Treadmill', 'Wallclock', 'Windchime', 'Wool', 'Wristband', 'aircraftcarrier', 'apill', 'blackboard', 'calendar', 'candle', 'chilipatse', 'clocksandwatches', 'doublefacedadhesivetape', 'firecrackers', 'funnel', 'honeybee', 'hot-waterbag', 'lion', 'lizard', 'notebook', 'palette', 'paper-cut', 'pencil-box', 'pineapple', 'plate', 'poster', 'preservedplum', 'pressurecooker', 'redwine', 'ricecooker', 'safetyhat', 'salad', 'sandbag', 'seal', 'smallbell', 'stapler', 'steamer', 'streetlamp', 'teatable', 'tiger', 'typewriter', 'whistling', 'wire']with open('en2ch.json', 'r') as f:	#加载英译中文件dic = json.load(f)captcha_path = 'D:/captcha/15689.jpg'	#原始验证码图片保存的路径#文字识别res_text, imgs_text = text_predict(captcha_path)#图像识别res_pic, pred_res, imgs_pic = pic_predict(captcha_path)res = captcha_pos(res_text, res_pic)#保存图片save(text_save_dir, res_text, imgs_text)save(pic_save_dir, pred_res, imgs_pic)

通过两部分的预测结果输出验证码的正确位置。第一排4张图片标号:1、2、3、4;第二排4张图片标号:5、6、7、8。

最终结果如下
在这里插入图片描述

以上是联合使用两个模型进行验证码预测的过程,接下来利用12306的验证机制,来实战测试两个模型联合使用的准确率。

import time
import base64
import requests
from urllib.parse import urlencodedef verify(count):#count用于计数正确识别的次数#验证码获取的基本链接,返回数据为base64编码的序列cap_base_url = "https://kyfw.12306.cn/passport/captcha/captcha-image64?login_site=E&module=login&rand=sjrand&"#验证码验证的基本链接,返回数据格式为json,其中包含状态码verify_base_url = 'https://kyfw.12306.cn/passport/captcha/captcha-check?'#用session来完成验证过程,保证请求过程的会话一致性session = requests.session()#为验证码获取链接加上时间戳,然后发起请求res = session.get(cap_base_url + str(int(time.time() * 1000)))img = base64.b64decode(res.json()['image'])  #解码之后的数据格式为io流img = Image.open(io.BytesIO(img))#原本输入text_predict、pic_predict两个函数的参数是图片的存储路径,#我这里直接输入的是图片本身,所以对judge_image_bk、split_image_text以及split_image这三个函数作了一点修改,也就是省去了函数中打开图片的这行代码#如果不想修改以上函数,也可以在这里加一行代码,先把得到的img保存到本地也行,具体存储路径自行定义res_text, imgs_text= text_predict(img)res_pic, pred_res, imgs_pic = pic_predict(img)res = captcha_pos(res_text, res_pic)if res:answers = []for i in res:  #计算得到验证码的像素坐标if i <= 4:answers.extend([str(40 + 72 * (i - 1)), str(73)])else:answers.extend([str(40 + 72 * (i - 5)), str(145)])data = {'answer': '', 'rand': 'sjrand', 'login_site': 'E'}data['answer'] = ','.join(answers)response = session.get(verify_base_url + urlencode(data))#状态码4表示成功if response.json()['result_code'] == '4':count += 1return True, count, imgreturn False, count, imgtext_model = model_load('text_model.h5')
model_pic = model_load('pic_model.h5')#标签
labels = ['Ants', 'Bandaid', 'Banner', 'Basketball', 'Beer', 'Boots', 'Bottleopener', 'Buscard', 'Candlestick', 'Cherry', 'Chineseknot', 'Coral', 'Cottonswab', 'Dashboard', 'DragonBoat', 'Earplugs', 'Electronicscale', 'Embroidery', 'Exhaustfan', 'Filebag', 'Flyswatter', 'Frenchfries', 'Gong', 'Jujube', 'MemorialGateway', 'Mop', 'Mungbean', 'Palmprint', 'Pyramid', 'Redbean', 'Refrigerator', 'Seagull', 'Seaweed', 'Spatula', 'Tapemeasure', 'Teacup', 'Tennisracket', 'Treadmill', 'Wallclock', 'Windchime', 'Wool', 'Wristband', 'aircraftcarrier', 'apill', 'blackboard', 'calendar', 'candle', 'chilipatse', 'clocksandwatches', 'doublefacedadhesivetape', 'firecrackers', 'funnel', 'honeybee', 'hot-waterbag', 'lion', 'lizard', 'notebook', 'palette', 'paper-cut', 'pencil-box', 'pineapple', 'plate', 'poster', 'preservedplum', 'pressurecooker', 'redwine', 'ricecooker', 'safetyhat', 'salad', 'sandbag', 'seal', 'smallbell', 'stapler', 'steamer', 'streetlamp', 'teatable', 'tiger', 'typewriter', 'whistling', 'wire']with open('en2ch.json', 'r') as f:	#加载英译中文件dic = json.load(f)count = 0
for i in range(100):  #一次性请求次数建议不要太多,如果你ip多也没问题status, count, img = verify(count)time.sleep(random.choice([0.1,0.2,0.3,0.4,0.5,0.8]))if status:print('第%d次验证码校验结果:成功!' % (i + 1))else:print('第%d次验证码校验结果:失败!' % (i + 1))#把识别错误的验证码保存下来,目录自定义,我这里的目录是'12306错误预测图'img.save(os.path.join(os.getcwd(), '12306错误预测图', str(i+101)+'.jpg'))
print('验证码校验成功率:%d' % count + '%')

经过多次测试,两个模型联合使用的实际准确率在90%左右。根据对识别错误的验证码分析,联合使用准确率有所下降的主要原因在于数据集中小部分的图片归类错误,因为是人工归类,有些两个种类的相似图片归类出错,还有些图片根本不知道是啥,主要是这个问题导致实际的准确率有小幅度的下降。不过,可以根据错误预测的验证码,来对之前的数据集进行修正,将实际的准确率提上来。
部分测试结果如下
在这里插入图片描述
在后续经过对训练集和验证集中部分错误图片的正确归类后,重新训练模型,经过实战测试,准确率就提升上来了,和模型训练过程中的准确率基本上是吻合的。
附上实战测试结果图,经过修正后,两个模型联合使用的整体准确率可稳定在97%,文本模型准确率基本上是100%。
在这里插入图片描述


http://chatgpt.dhexx.cn/article/NIKE30g7.shtml

相关文章

php实现12306验证码,PHP仿12306图片验证码

生成验证码的demo使用模型model读取图库&#xff0c;有需要对接框架的朋友可以自己修改&#xff0c;如下&#xff1a; # 引入测试的数据库model require_once dirname(__FILE__)./Model.php; # 引入验证码核心类库 require_once dirname(dirname(__FILE__))./vendor/Vif.php; $…

python 爬取12306验证码

一个简单的验证码爬取程序 本文介绍了在Python2.7环境下爬取网站验证码&#xff1a; 思路就是获取验证码对应的url&#xff0c;然后发起requst请求&#xff0c;读取该URL对应的内容&#xff0c;然后写入到一个本地文件&#xff0c;实现一个验证码的保存。大量下载可以把以上程…

利用百度AI平台识别12306验证码

简单的利用百度AI平台做一个12306的验证码识别。 第一步&#xff1a;先进行图片预处理 提取文字部分 import numpy as np#分割文字 def get_img_text(img,offset0):return img[3:22,120offset:177offset]#分割图片 def _get_imgs(img):interval 5length 66img_array np.em…

12306验证码为什么那么变态?都是这项深度学习应用给逼的

导读&#xff1a;12306为什么要设置那么复杂的验证码机制呢&#xff1f;就是因为OCR。 今天聊OCR。 OCR是人工智能、机器学习特别是深度学习&#xff0c;在图像识别方向最为重要的应用之一。OCR全称Optical Chararcter Recogition&#xff0c;中文翻译为光学字符识别&#xff0…

12306验证码的一些思考

12306的验证码长这个样子: 让选择图片.看起来非常完美的图片验证码.比那些简单又没有实用的字母数字验证码组合强太多了.那些字母数字组合直接获取图片光学识别然后填进表单就可以攻破. 我也想实现这样的. 怎么去实现呢? 设计一个简单点的吧. 1.我先收集图片.收集200张.分…

12306 验证码代码分析

验证码是一个很有趣的问题&#xff0c;其目的是谁是一个人或机器输入来区分&#xff0c;这个问题的实质是一个图灵测试&#xff08;推荐电影《模仿游戏》&#xff09;&#xff0c;验证码是一种简单而有效的验证方法&#xff0c;由CMU在教授2000在有关创建。后来这头牛谁又将收集…

Python——12306图片验证码

本次爬虫&#xff0c;我们来模拟一下12306的验证码验证 本次练习用到的模块&#xff1a; requestsrebase64urllib3 第一步&#xff0c;按F12查看验证码图片的信息&#xff1a; 提取URL&#xff1a;https://kyfw.12306.cn/passport/captcha/captch…

debian安装docker(通用方法)

本教程源于官网教程进行解释官网教程 docker容器是一个可以同时跑青龙&#xff08;用于挂机脚本&#xff09;与宝塔&#xff08;用于便携式部署网站&#xff09;之类的工具 我安装时在网络上搜索的教程来在部分电脑或者是主机上有时会出错尤其是32位系统的 于是我在疯狂百度总…

Debian安装mysql

Debian 10系统中默认使用了MariaDB&#xff0c;在APT的软件源中并没有mysql。所以&#xff0c;Debian 10 如果要安装mysql&#xff0c;需要下载安装Mysql APT Repository&#xff0c;更新APT Repository 后再使用 apt-get 安装。 设置软件源 点击mysql下载地址&#xff0c;下载…

linux Deploy 安装debian

一 准备工作 1、一台root的魅蓝note6手机&#xff0c;手机root教程需要自己根据机型搜索 2、去 https://github.com/meefik/linuxdeploy/releases下载linux deploy 3、去https://github.com/meefik/busybox/releases 下载BusyBox (安卓平台虚拟机&#xff08;chroot运行linux的…

Debian10安装

Debian 10.7(buster) 使用bt文件下载 下载链接&#xff1a;https://cdimage.debian.org/debian-cd/current/amd64/bt-dvd/ 这次是在VMware Workstation上安装的&#xff0c;如果是想在实体机上安装的话&#xff0c;需要做个启动盘&#xff0c;就是把ISO文件刻录到USB或DVD上。…

debian安装和基本使用

debian安装和基本使用 由于centos停止更新&#xff0c;改用debian debian下载&#xff0c;官网去下载DVD版本&#xff0c;4g多的体量&#xff0c;包含的软件比较全。 虚拟机安装&#xff0c;如果进入安装界面直接黑屏卡死&#xff0c;要注意是否镜像ISO文件未加挂。手动在虚拟…

Debian10: 系统安装

若非虚拟机安装&#xff0c;需要制作启动U盘&#xff0c;备份好U盘的数据后&#xff0c;使用UltraISO工具或Rufus(http://rufus.ie/)将 debian-10.6.0-amd64-DVD-1.iso文件写入U盘&#xff0c;将此U盘插入服务器&#xff0c;设置服务器从U盘启动即可。 第一步&#xff1a;选择…

安装debian11系统

镜像下载地址&#xff1a;https://gemmei.ftp.acc.umu.se/debian-cd/current/amd64/iso-cd/debian-11.6.0-amd64-netinst.iso 一、选择图形化安装&#xff08;这里说一下&#xff0c;这里的图形化安装是安装过程是图形化的&#xff0c;并非是选择系统带图形化界面&#xff0c;…

Debian 系统安装,小白教程

大家好&#xff0c;我是橘子。在工作过程中呢遇到了很多问题&#xff0c;踩了很多坑。网上很多都有教程但总是缺胳膊少腿&#xff0c;说了大概但坑似乎依旧存在。从今天开始&#xff0c;我会将自己碰到的一些坑和如何解决的分享给大家。如果你是个大佬&#xff0c;那我的内容对…

最新发布 Debian 系统的详细安装过程

前言 Debian 究竟是什么&#xff1f;有官方详细介绍说明&#xff0c;在此就不过多介绍说明了&#xff0c;只告知官网&#xff0c;可点击查看官网介绍。 管网连接 &#xff1a;Debian -- About Debian https://www.debian.org/intro/about 平台准备 使用 VMware 平台搭建&…

Debian 11 安装,超详细!

安装装备 华为源中下载镜像 https://repo.huaweicloud.com/debian-cd/11.0.0/amd64/iso-cd/ 3A服务器的虚拟机 开始安装 配置虚拟机 直接回车即可&#xff0c;第一次安装的小伙伴可以选择中文版安装&#xff0c;这样方便易懂&#xff0c; 一路继续&#xff0c;配置网络&a…

如何轻松安装 Debian Linux 系统

安装 Debian 的轻松程度依赖于选择什么镜像。 如果你使用 Debain 官网的默认 ISO 镜像&#xff0c;安装 Debian 就比较费劲。你会卡在这种界面&#xff0c;让你从外部可移动介质上安装网络驱动。 对于新用户来说&#xff0c;从默认的 ISO 中安装 Debian 是有问题的 当然你可以…

IOC 是什么

Ioc—Inversion of Control&#xff0c;即“控制反转”&#xff0c;不是什么技术&#xff0c;而是一种设计思想。在Java开发中&#xff0c;Ioc意味着将你设计好的对象交给容器控制&#xff0c;而不是传统的在你的对象内部直接控制。如何理解好Ioc呢&#xff1f;理解好Ioc的关键…

什么是 IoC 容器?

什么是 IoC 容器&#xff1f; 这个问题我觉得可以拆分为 3 小问&#xff1a; IoC 是什么意思&#xff1f;容器 指什么&#xff1f;IoC 容器是什么&#xff1f; 首先对于 IoC Inversion Of Control 翻译过来即 控制反转。理解 ”控制反转“ &#xff0c;我觉得首先是要明白&a…