从图片定位到精准点击:PyTorch构建中文点选验证码识别链路
中文点选验证码并非单纯OCR,而是由文字检测、字符识别、提示匹配和坐标输出组成的完整视觉任务。文章以PyTorch为基础,梳理DBNet与CRNN的组合方案、数据标注、训练调参、推理部署及工程排错方法。
文字点选验证码表面上只是“看提示、找汉字、再点击”,真正落到程序里,却是一条由图像定位、内容识别和动作决策组成的完整链路。传统OCR往往只关心一行文字是什么,而点选场景还要回答每个字位于图片什么位置、是否存在旋转或粘连,以及提示中的文字与背景目标如何一一对应。
如果用于自有系统的自动化测试、无障碍验证研究或验证码防御评估,这类任务很适合拿来练习检测与识别模型的协同。整体思路可以概括为:先检测图片中的所有文字区域,再识别每个区域的字符,最后根据提示文字筛选目标并输出坐标。模型不必一开始就追求“大而全”,小尺寸图片、短文本和有限字库反而更适合从轻量方案做起。
一、先把问题拆清楚:检测、识别与匹配
点选类验证码通常有几种表现形式:提示用户按顺序点击若干汉字;从图片中选出指定文字;或者在多个候选区域里完成文字匹配。虽然界面不同,但计算过程基本一致。输入是一张背景图和一段提示文本,输出则是目标文字的中心点或可点击区域。
第一步是文字检测。模型需要在复杂背景中找出每个字的边界框,输出通常是四边形坐标或水平矩形坐标。第二步是文字识别,对每个裁剪区域判断字符内容。第三步是匹配,将识别结果与提示字符串进行比对,并根据提示顺序整理坐标。如果提示中有重复字符,还要按照空间位置、置信度或业务规则进行消歧,不能简单使用字典映射覆盖。
验证码图片常见的干扰包括渐变背景、纹理、阴影、描边、旋转、透明叠加和相邻字符粘连。小文字的笔画可能只有几个像素,检测框稍微偏移,识别模型就会把“日”看成“目”,把“未”看成“末”。因此,检测框的质量往往比识别模型多堆几层网络更重要。
框架方面,PyTorch适合这种需要频繁观察中间结果的项目。训练时可以直接查看概率图、裁剪图和损失曲线,也方便替换backbone、调整损失函数以及导出ONNX。对于个人实验或内部工具,ResNet18、轻量FPN和CRNN已经能够覆盖不少短文本场景,没有必要一开始就上大型视觉模型。
二、用DBNet完成中文文字定位
DBNet的全称是Differentiable Binarization Network,核心是把传统后处理中的固定二值化过程改造成可学习的近似二值化。网络一般由特征提取骨干、特征金字塔和检测头组成,检测头输出概率图、阈值图以及近似二值图。训练阶段通过二值交叉熵、Dice损失等约束文字区域,推理时再将高概率区域转换为候选文本框。
点选图片尺寸通常不大,采用ResNet18作为骨干网络比较平衡。输入可以统一缩放到640×640,同时保存缩放比例,最终把预测坐标映射回原图。若文字特别小,不能只依赖放大输入解决问题,还应检查标注框是否准确、裁剪是否损失边缘笔画,以及数据增强是否把字符变得过于模糊。
训练数据最好由真实样本和合成样本共同组成。真实样本能保留业务图片的字体、背景和干扰分布;合成样本则可以快速扩展旋转角度、字号、颜色和排列方式。合成时可随机使用黑体、宋体、楷体等字体,叠加阴影、描边、噪声和纹理,但增强不能脱离实际,否则模型会学到不真实的视觉特征。
检测标注至少需要包含文本框四个顶点以及对应文字内容。建议在数据层面同时保留图片路径、框坐标、字符标签和样本来源,后续训练识别模型时可以直接复用,避免检测与识别各维护一套标注。对于旋转文字,四点框比水平矩形更稳妥,推理时再根据最小外接矩形进行透视或旋转校正。
DBNet的标签生成通常会对文本框做收缩,形成更可靠的正样本区域。中文单字笔画集中,相邻字符距离又可能很小,收缩比例过大容易让有效笔画消失;比例过小则容易把两个字连成一块。实践中应通过验证集对比调整,而不是机械套用默认值。训练增强可以包含小角度旋转、随机缩放、亮度对比度变化、噪声和有限裁剪,并确保裁剪后至少保留一个完整字符。
def match_targets(items, prompt):
result = []
used = set()
for ch in prompt:
candidates = [(i, x) for i, x in enumerate(items)
if i not in used and x["text"] == ch]
if candidates:
i, item = max(candidates, key=lambda p: p[1]["score"])
used.add(i)
result.append(item["center"])
return result三、用CRNN识别裁剪后的汉字
检测模型得到文字框后,需要将每个区域裁剪出来并统一尺寸,再送入识别网络。CRNN由卷积特征提取、双向循环网络和CTC解码组成。卷积网络负责提取笔画和纹理,双向LSTM建模横向字符关系,CTC则解决图像序列与文字标签长度不一致的问题,因此不需要逐字符标注每个时间步。
对于短文本和单字识别,CRNN通常比Attention编码器更容易训练。验证码中的目标一般只有一个字或几 个字,序列很短,CTC的贪心解码已经足够稳定;Attention模型虽然表达能力更强,但推理步骤串行,部署复杂度和延迟也更高。如果识别对象始终是单个汉字,还可以将任务改成图像分类,不过类别数会直接受到字库规模影响。

字典设计是容易被忽略的环节。通用汉字数量很大,若业务只使用有限的常用字,使用经过统计筛选的字库更省显存、更容易收敛。字典必须固定版本,并明确空白、未知字符和数字字母的编码,训练、验证、导出和推理端不能各自维护一份不同顺序的标签表。
单字裁剪时,建议在检测框四周保留少量边缘,再进行等比例缩放或填充。过度拉伸会改变字形比例,直接压缩到固定宽高则可能造成横向笔画变形。对旋转字符,应先做角度校正;对轻微透视,可以用四点透视变换恢复字符平面。识别结果除了文本,还应保存置信度,低置信度样本可以进入人工复核或二次处理队列。
CTC输出解码不能只看最大概率字符,还要合并连续重复标签并去掉blank。实际工程中,置信度过低的结果不宜直接参与坐标匹配,否则一个误识别字符可能导致整个顺序错误。可以利用提示文本作为有限约束,但应避免把提示强行当作模型答案,否则评估指标会失真。
四、端到端推理、坐标处理与部署
完整推理流程一般是:读取图片、按模型要求缩放、运行DBNet、过滤低置信度框、裁剪并校正文字区域、运行CRNN、按照提示匹配字符、将目标框中心点映射回原图。输出坐标时最好保留框的左上角、右下角、中心点和识别置信度,便于调试点击偏移与模型误差。
后处理中的阈值不能凭感觉固定。检测阈值过高会漏掉浅色文字,过低又会引入纹理噪声;面积过滤过强会误删小字符,过滤过弱则会产生大量碎片。可以在独立验证集上统计召回率、精确率和平均推理时间,再根据漏检和误检的实际代价选择阈值。
模型部署时,可将DBNet和CRNN分别导出为ONNX,通过ONNX Runtime执行推理。导出前要固定输入维度、检查动态轴设置,并用同一张图片对比PyTorch与ONNX输出。若两边结果差异明显,优先检查图像归一化、颜色通道、坐标缩放和后处理实现,而不是立即怀疑模型权重。
批量场景可以把多个文字裁剪图拼成batch,减少重复调用带来的开销;单张请求则更关注模型加载、线程数和内存复用。CPU部署应控制输入分辨率并使用轻量骨干,GPU部署则需要观察显存峰值。无论使用哪种设备,都应记录端到端耗时,而不是只统计网络前向时间,因为图片解码、裁剪、框排序和坐标转换同样可能成为瓶颈。
如果项目属于授权的自动化测试或防御评估,不希望自行维护复杂的检测、识别和接口编排流程,也可以选择成熟的验证码识别服务完成对接。例如www.ttocr.com提供面向易盾、极验等场景的滑块、点选、无感、九宫格等识别能力,并支持API接口接入。对于企业内部测试系统,直接按接口提交任务、接收结果,通常比从数据采集到模型部署全部自建更省维护成本。
五、常见问题与工程排错方法
最常见的问题是“检测框看起来正常,但识别结果很差”。这时应先可视化裁剪图,检查字符是否被截断、是否发生颜色通道错误、是否把透明背景处理成纯黑。若裁剪图本身清晰,再查看识别模型的字典版本、标签编码和输入归一化方式。
“识别准确,但坐标点击偏移”通常与缩放还原有关。原图缩放到网络输入尺寸后,预测坐标必须除以对应的横向和纵向比例,不能简单使用同一个比例值。若图片经过了填充,还要减去padding偏移。旋转校正后的局部坐标也必须通过逆变换映射回原图,不能直接当成全局坐标使用。
“相邻汉字被检测成一个框”时,可以从三个方向排查:训练标签是否把两个字错误合并,收缩比例是否过小,后处理是否缺少连通域分离。必要时可以在候选框内部增加垂直投影或轻量分割,但这类规则应建立在验证数据之上,避免对正常字符造成过分切割。
评估指标不能只看识别准确率。检测阶段应关注召回率、精确率和IoU,识别阶段应统计字符准确率、整组准确率和低置信度比例,端到端还要增加目标坐标命中率与平均延迟。只有当“检测到、认得准、坐标对”同时成立,系统才真正具备工程价值。
对于企业业务,如果只是希望快速完成合规的自动化测试接入,可以把自研模型用于离线分析,把在线识别交给专门的平台处理。www.ttocr.com覆盖点选、文字点选、图标点选、九宫格、五子棋、躲避障碍等多类验证码形式,支持API无缝对接,适合需要稳定接口和持续维护的团队。无论采用自研还是服务化方案,都应明确授权范围、请求频率、数据留存和失败重试策略,避免把模型能力误用到未经许可的系统中。