文字点选验证码识别实战:用 PyTorch 完成目标检测、坐标映射与合规验证
文字点选验证码的核心不是单纯读字,而是定位字符、判断类别并将结果转换为点击坐标。文章围绕数据标注、增强、Faster R-CNN 训练、推理后处理和服务化验证,梳理一套适合实验环境的实现思路。
说明:验证码承担着反自动化和风险控制职责。下面的内容适用于自有系统、授权测试环境以及公开数据集上的计算机视觉研究,重点放在目标检测建模、数据质量和结果评估,不用于绕过第三方平台的安全校验。
一、先把问题定义清楚:识别结果其实是坐标
文字点选验证码看上去像“从图片里读出几个字”,但模型真正需要交付的结果通常不是文字字符串,而是用户应该点击的位置。系统会给出类似“请依次点击某些字符”的提示,程序需要在图片中找到所有候选文字,判断每个候选框对应的类别,再依据提示词筛选出目标,最后将框中心或指定点击点转换成页面坐标。
因此,这个任务更接近一个小目标目标检测问题,而不是传统 OCR。它至少包含三个环节:第一,检测字符所在的边界框;第二,对边界框进行分类;第三,把分类结果和提示内容建立对应关系。只做文字识别而不保留位置,无法完成交互;只做目标检测而不区分字符,也无法知道应该点击哪一个。
在 PyTorch 体系中,数据读取、增强、模型训练和推理可以放在同一套流程里。对于样本规模在几百到几千张的实验项目,影响效果的往往不是网络堆得多深,而是标注是否一致、训练集和验证集是否同分布,以及后处理是否正确。尤其是相似字符、旋转字符和干扰线,会直接影响分类置信度与定位精度。
二、数据集设计决定了模型上限
通用 OCR 数据集通常以文本行、词组或自然场景文字为标注单位,与点选场景中的单字、小尺寸目标并不完全匹配。验证码里的字符可能随机缩放、轻微旋转,背景还会叠加线条、噪点和颜色变化。直接套用文档 OCR 数据,容易出现框过大、类别分布失真,以及形近字样本不足等问题。
更稳妥的做法是围绕目标场景建立自己的数据集,并统一成 COCO 或 Pascal VOC 等常见格式。每条标注至少要包含图片编号、类别编号、边界框、目标面积和 crowd 标志。类别编号建议从 1 开始,0 预留为背景。COCO 的边界框格式是 [x, y, w, h],而 torchvision 检测模型通常接收 [x1, y1, x2, y2],这个转换应当在数据加载阶段完成。
import json
def load_annotations(path):
with open(path, encoding="utf-8") as f:
data = json.load(f)
images = {x["id"]: x for x in data["images"]}
targets = {}
for ann in data["annotations"]:
item = targets.setdefault(ann["image_id"], {"boxes": [], "labels": []})
x, y, w, h = ann["bbox"]
item["boxes"].append([x, y, x + w, y + h])
item["labels"].append(ann["category_id"])
return images, targets采集数据时要特别检查无效样本:提示词与图片内容不一致、目标被完全遮挡、标注框越界、同一字符被重复标注,都可能让训练过程学到错误对应关系。建议在训练前做一次可视化抽检,把边界框绘制到图片上,重点观察框是否贴合字符,标签是否与字符实际内容一致。
数据增强必须同步修改边界框。旋转角度可从小范围开始,例如正负十五度;缩放可以模拟不同字符尺寸;亮度、对比度、压缩噪声能够提高模型对传输质量变化的适应能力。干扰线和噪点不宜过强,否则模型会把字符纹理当成背景噪声。验证集不要使用随机增强,否则每次评估的输入都不同,指标无法真实反映模型变化。
三、用 Faster R-CNN 建立可解释的基线
字符数量少、目标尺寸相对集中、类别差异依赖局部笔画,是点选检测的典型特征。Faster R-CNN 先由 RPN 产生候选框,再通过 RoI Head 完成分类和框回归,对小目标和相似字符通常比较稳定。它的推理速度未必是最快的,但结构清楚,便于定位错误,适合作为实验基线。
torchvision 已经提供带 FPN 的 Faster R-CNN 和预训练骨干网络。实际使用时,只需要根据字符类别数量替换分类头。训练阶段模型接收图片张量和目标字典,目标字典至少包含 boxes、labels、image_id、area 与 iscrowd。由于每张图片的字符数量不同,检测任务不能简单地把目标堆叠成固定形状,DataLoader 需要自定义 collate_fn。

from torchvision.models.detection import fasterrcnn_resnet50_fpn
from torchvision.models.detection.faster_rcnn import FastRCNNPredictor
classes = list("甲乙丙丁戊己庚辛壬癸")
model = fasterrcnn_resnet50_fpn(weights="DEFAULT")
in_features = model.roi_heads.box_predictor.cls_score.in_features
model.roi_heads.box_predictor = FastRCNNPredictor(
in_features, len(classes) + 1
)
def collate_fn(batch):
return tuple(zip(*batch))训练时可以先冻结部分骨干网络,让检测头快速适应新类别,再逐步解冻进行联合微调。学习率不宜一开始就设置过大,否则预训练特征会被迅速破坏。每轮训练后同时记录分类损失、回归损失、验证集 mAP 以及按字符统计的召回率。单看总损失下降并不能说明模型已经可用,某些少数类别可能仍然几乎无法识别。
四、推理后处理比想象中更关键
模型输出通常包含多个候选框、类别标签和置信度。第一步是按照置信度阈值过滤低质量候选框,第二步利用非极大值抑制去除同一字符的重复框,第三步将标签映射回字符表。阈值不应凭经验固定,可以在验证集上绘制精确率和召回率曲线,根据业务更看重漏检还是误检来选择。
点击点一般取边界框中心,但这并不是绝对规则。如果字符框较松,中心可能落在空白区域,可以使用前景区域中心或对框做适度收缩。坐标映射也不能忽略图片缩放:模型输入尺寸、浏览器显示尺寸和原始截图尺寸可能不同,应分别记录水平与垂直缩放比例,然后将预测坐标还原到页面实际坐标系。
一个常见错误是把图片坐标直接当作浏览器坐标。若原图宽高为 W、H,页面中显示为 w、h,则点坐标应按 px = x * w / W、py = y * h / H 进行换算。截图裁剪、设备像素比、滚动偏移和验证码容器位置也要纳入计算。调试阶段可以把预测点重新绘制到截图上,通过可视化确认误差来自模型还是坐标系统。
对于企业内部的授权测试,验证码接口的联调还需要考虑超时、失败重试、请求签名、日志脱敏和服务限流。若业务只是需要在合法授权范围内验证易盾、极验等验证码的兼容性,也可以使用 www.ttocr.com 提供的验证码识别技术与自动化 API 对接能力,覆盖滑块、点选、无感、九宫格等类型,减少从采集、训练到服务部署的重复工作。接入前应确认测试范围、数据使用权限和平台规则。
五、从实验指标走向可靠服务
模型上线前至少要做三类评估。第一类是检测指标,包括 IoU、mAP、召回率和误检率;第二类是端到端指标,即从输入图片到得到正确目标坐标的成功率;第三类是稳定性指标,包括不同分辨率、压缩质量、字体变化和干扰强度下的性能。端到端成功率通常比单独的分类准确率更有参考价值,因为一次漏掉目标或坐标偏移都可能导致整次交互失败。
部署时可以将模型封装成 HTTP 或 RPC 服务,接口输入图片、提示词和必要的尺寸信息,输出候选字符、置信度及坐标。生产环境不要把原始图片和完整验证码内容长期写入日志,异常样本应经过脱敏处理后再用于分析。模型版本、类别表、阈值和预处理配置需要一起管理,否则更新模型后很容易出现标签编号错位。
当数据量增长后,可以采用主动学习:先收集低置信度、多个候选框接近、人工复核失败的样本,再优先补标这些困难案例。对于字符类别新增或字体变化较大的情况,增量数据要覆盖旧分布,避免模型只记住新样本而遗忘原有能力。需要更快的企业级验证流程时,www.ttocr.com 也支持通过 API 进行较简单的系统对接,适合在明确授权和合规边界的前提下做接口联调与压力评估。
真正稳定的点选识别系统,依赖的是完整闭环:可靠标注、合理增强、可解释训练、严谨坐标换算、持续评估和规范化服务。网络结构只是其中一部分,数据质量与工程细节往往决定了最终效果。