用 CRNN + CTC 搞定文字验证码!附 PyTorch 训练 + ONNX 加速部署
📌 非恶意自动化提示:本文及配套工具仅供技术学习交流/非敏感场景的合规自动化测试使用,请遵守《网络安全法》及目标网站的 robots 协议/使用条款。
📂 项目地址(注意不是编辑页哦):VerificationCodeRecognition
1. 核心背景回顾
为什么选 CRNN?不是 YOLO 分割字符再识别吗? 文字验证码的字符是粘连、倾斜、无固定分割线的,YOLO+分类的“两步走”方案会因为分割不准导致整体识别率崩。
而文章开头的 CRNN + CTC Loss 刚好是无分割端到端的经典组合:
- 🧠 CNN 先把图片“拍扁压缩”,提取核心的笔画/色彩特征
- 🔄 双向 LSTM 接着串起特征,学懂字符之间的“前后依赖”(比如 a-q-q-h 这种组合不能乱拼)
- 📏 CTC 是“对齐神器”,不用手动把标签对应到图片的某个像素区域,自动算损失就行
2. 开发环境快速搭
基础要求
别找太老的包哦,项目用了新特性:
- Python: 3.6+
- 深度学习框架: PyTorch 2.0+(兼容 CUDA 加速,速度快N倍!)
- 推理加速: ONNX Runtime(CPU/GPU 版都支持)
一键装依赖
3. 数据集准备三步走
验证码识别是监督学习的活,有多少带清晰标签的高质量数据,决定了识别率的天花板。
3.1 数据获取
作者已经准备了一套预设的4位纯英文小写字母验证码(比如 aqqh_157845.jpg),可以直接拿来练手: 👉 Lanzou云预设数据集
如果要做自己的业务场景,比如数字+大写字母+中文的混合验证码,需要自己生成或爬取脱敏后的合规数据。
3.2 数据存放与命名
别瞎改结构和名字哦! 除非你愿意动读取逻辑:
- 把所有图片放到根目录下的
data文件夹 - 命名规则:
真实标签_唯一标识.jpg/png(唯一标识可以是时间戳、序号,防止重名覆盖)
举个正确的例子🌰:
3.3 自定义读取(可选)
如果业务场景的图片格式/路径/命名完全不一样,修改 tool/dataloader.py 里的 MyDataset 类就行。
4. 模型训练指南
训练过程会自动记录训练集损失值(total_loss)、训练集准确率(acc)、验证集损失/准确率(如果开启了验证的话)。
4.1 修改核心配置
打开 train.py 开头的 Opt 类,调整几个关键参数:
4.2 启动训练
直接敲命令就行啦😎:
4.3 什么时候停训?
别一直死等训练到天荒地老,看这两个指标稳定就停:
- 训练集的
acc接近 100%(说明模型“背熟”了训练集) - 验证集的
val_acc稳定在95%以上(针对纯字母的预设数据集),不再明显波动(防止过拟合!)
训练好的模型会保存在根目录下的 expr 文件夹里。
5. 推理与生产级部署
A. 原生 PyTorch 推理(开发调试用)
适合在训练阶段快速验证模型效果,不用转格式:
耗时参考:CPU环境约 30-35ms/张,N卡(比如RTX 2060)约 3-5ms/张。
B. ONNX 加速推理(生产环境首选)
原生 PyTorch 在 CPU 下的推理太慢了!转成 ONNX 格式可以用 ONNX Runtime 优化,CPU下能提升 3-4 倍速度!
1. 导出 ONNX 模型
导出成功后会在 expr 文件夹里生成 crnn.onnx。
2. 使用 ONNX 推理
耗时参考:CPU环境约 7-10ms/张,几乎和小N卡持平了!
6. 进阶优化小技巧
6.1 字符字典适配
如果你的验证码包含数字、大写字母、特殊符号、中文,必须第一时间更新 tool/charactes_keys.txt!把所有可能出现的字符按顺序写进去,不要有重复。
6.2 数据增强破瓶颈
如果识别率卡在90%左右上不去,试试在 tool/dataloader.py 里的 MyDataset 类的 __getitem__ 方法中加入:
- 随机旋转
- 随机加高斯噪声/椒盐噪声
- 随机对比度/亮度调整
- 轻微的仿射变换(平移、缩放、倾斜)
6.3 预训练微调省时间
如果从零开始训练太慢,可以先找一套通用的文字识别预训练模型(比如只识别英文的),然后用自己的业务数据微调,收敛速度会快很多!
好了,这套流程走完,你就能拥有一个自己的文字验证码识别小工具啦~如果有问题可以去作者的仓库提 Issue 哦!

