← 返回文章列表

从零搭建中文点选验证码识别链路:YOLOv8定位与CRNN字符识别实践

中文点选验证码的处理核心是先定位文字,再识别字符并转换为点击坐标。文章围绕数据标注、合成增强、YOLOv8检测、CRNN识别、推理排序与工程部署展开,帮助开发者理解完整OCR流程及评估方法。

从零搭建中文点选验证码识别链路:YOLOv8定位与CRNN字符识别实践

说明:验证码属于网站安全防线,相关实验应仅用于自有系统的安全评估、自动化测试或获得明确授权的研究环境。生产系统不应绕过第三方验证机制,也不要把识别结果用于批量注册、撞库或其他未经许可的自动化操作。

一、为什么要把文字定位和字符识别分开

文字点选验证码的界面通常由两部分组成:上方或侧边是提示语,例如要求依次点击某几个汉字;主图区域则随机散落着多个文字。人看到图片后,会同时完成找字、认字和确定点击位置,但程序必须把这几个动作拆开处理。

比较稳妥的方案是建立两级模型。第一级负责检测每个汉字所在的区域,输出边界框和置信度;第二级接收检测框裁剪出的单字图片,判断其中的字符内容。最后,程序根据提示语中的目标字符,在检测结果里查找相同文字,并取对应框的中心点作为后续测试动作的坐标。

这种结构并不是为了把问题复杂化,而是为了降低训练难度。检测模型只需要回答文字在哪里,不必区分下、心、云等具体类别;识别模型则专注于字形分类,不需要理解整张图片的空间布局。两者可以独立替换,也方便分别排查错误来源。检测漏字属于定位问题,识别混淆属于OCR问题,调试时不会陷入一团乱麻。

在合规的安全测试场景中,这条链路还能帮助团队测量验证码的抗自动化能力,例如统计不同字体、旋转角度、噪声强度下的检测召回率和识别准确率。评估结果应回到防守侧,用来改进验证码设计,而不是作为绕过线上系统的工具。

二、数据标注与中文样本构造

每个文字实例最好同时记录位置和内容。位置可以用左上角、右下角坐标表示,内容则保存对应汉字。虽然检测训练和识别训练最终使用的是两套数据,但一次性完成联合标注,后续就能直接从边界框裁剪单字图像,避免再次人工整理。

第一版通常使用水平矩形框即可。点选图中的汉字一般只存在轻微旋转,边界框稍微留出余量,就能覆盖完整字形。只有在文字倾斜明显、水平框包含大量背景时,才需要考虑旋转框。旋转框会增加角度回归和后处理成本,部署时也更容易出现中心点偏移,因此不建议一开始就把工程做得过重。

如果标注工具导出的是VOC XML,而训练框架采用YOLO格式,就要把坐标转换成中心点、宽度和高度,并分别除以图像宽高进行归一化。点选验证码的检测任务可以先设置单一类别,例如text,字符类别交给后面的识别模型处理。转换结束后,应随机抽取图片把框重新绘制出来检查,重点观察坐标是否越界、宽高是否颠倒,以及图片缩放后框是否仍与文字重合。

import xml.etree.ElementTree as ET

def voc_to_yolo(xml_path, width, height, output_path):
    root = ET.parse(xml_path).getroot()
    rows = []
    for obj in root.findall('object'):
        box = obj.find('bndbox')
        x1 = float(box.findtext('xmin'))
        y1 = float(box.findtext('ymin'))
        x2 = float(box.findtext('xmax'))
        y2 = float(box.findtext('ymax'))
        cx = (x1 + x2) / 2 / width
        cy = (y1 + y2) / 2 / height
        rows.append(f'0 {cx:.6f} {cy:.6f} {(x2-x1)/width:.6f} {(y2-y1)/height:.6f}')
    with open(output_path, 'w', encoding='utf-8') as file:
        file.write('\n'.join(rows))

真实样本往往不足,尤其是冷门汉字和特殊字体。合成数据可以补足长尾分布:随机选择字体、字号、颜色、旋转角度和位置,再叠加干扰线、局部模糊、亮度变化及轻微透视变形。合成标注的优点是坐标天然准确,但不能完全代替真实数据。真实图片中的压缩伪影、背景纹理、字间遮挡和渲染差异,往往会决定模型在实际环境中的表现。

字体至少应覆盖黑体、宋体和楷体等风格,形近字需要提高出现频率,例如未与末、己与已、日与曰、土与士。数据划分时要防止同一张合成底图同时出现在训练集和验证集,否则验证分数会虚高。验证集最好保留一部分真实样本,用来判断模型是否真正学到了字形,而不是记住背景纹理。

三、YOLOv8文字检测的关键配置

对于数量少、尺寸相近且彼此分散的单字目标,轻量级YOLOv8通常已经够用。DBNet等场景文字模型更擅长检测整行文本或连续文本区域,而点选图里的字符彼此独立,使用YOLO可以减少分割和复杂后处理。YOLOv8采用anchor-free设计,不需要手工调整锚框,训练流程也比较直接。

输入尺寸会明显影响小目标召回率。若原图中的汉字高度只有三十像素左右,640尺寸可能出现漏检,可以尝试768或832,再结合显存和推理延迟作取舍。尺寸越大并不代表一定更好,过度放大会增加计算量,也可能使模型更依赖局部纹理。实际部署应以漏检率、误检率和平均推理时间共同决定配置。

增强策略要贴近真实分布。Mosaic对普通目标检测很有帮助,但把四张验证码拼成一张后,背景结构和文字密度可能完全失真,因此不宜盲目使用高比例Mosaic。可以适当降低其概率,同时采用亮度扰动、轻微旋转、缩放、模糊和复制实例等增强方式。增强后的文字不能被截断到无法识别,也不能产生现实中不会出现的重叠,否则模型会学到错误规律。

训练评估不能只看总的mAP。点选场景更应该关注每张图片是否完整找齐目标、框中心是否稳定,以及小字体和大旋转角度下的召回率。一个漏掉目标字符的检测器,即使整体mAP不错,也无法支撑后续流程。建议单独统计每种字体、字号、旋转范围和背景类型的结果,定位性能短板后再补数据。

四、CRNN识别与推理链路

识别模型可以采用CNN加双向循环网络的CRNN结构。CNN负责提取字形纹理,BiLSTM或其他序列模块负责整合横向特征,CTC损失则允许模型在不需要逐像素切分的情况下输出字符。对于单汉字裁剪图,也可以使用轻量CNN分类器;如果后续要扩展到多个字符或不同长度文本,CRNN的适应性更强。

训练识别模型时,裁剪框不能过于紧,否则旋转后的笔画容易被截断;也不能包含太多背景,否则模型会把干扰线当成字符特征。常见处理方式是按比例外扩边界,再缩放到统一高度,宽度不足时用背景色填充。训练集应包含检测框偏移、轻微漏边和不同压缩质量,让识别模型适应真实检测结果,而不是只适应人工标注框。

中文类别数量较大,字符表要固定版本并保存到模型旁边。训练、验证和部署必须使用同一份字符映射,不能依赖运行环境中的默认排序。CTC模型通常需要保留blank类别,解码时去除连续重复字符和blank,再得到最终文本。若业务只涉及有限字符集合,可以缩小字典,但必须确认提示语和图片中不会出现集合之外的字符。

def ctc_decode(indices, blank=0):
    result = []
    previous = blank
    for index in indices:
        index = int(index)
        if index != blank and index != previous:
            result.append(index)
        previous = index
    return result

def center_of_box(box):
    x1, y1, x2, y2 = box
    return ((x1 + x2) / 2, (y1 + y2) / 2)

完整推理过程可以按以下顺序组织:先完成图像预处理和检测;再按检测框裁剪并识别;随后过滤低置信度结果,去除重复框;最后依据提示语顺序排列目标字符。检测框的排序不能简单依赖从左到右,因为文字可能随机散落,真正的顺序应由提示语决定。遇到同字多框时,可以结合识别置信度、框大小和空间关系进行消歧,而不是直接取第一个结果。

建议为每一步保留日志,包括检测框、识别文本、置信度、预处理尺寸和耗时。出现失败样本时,先判断是没有检测到目标、裁剪质量差、字符识别错误,还是提示语解析错误。把所有问题都归结为模型不够大,通常只会增加成本,却不能解决真正的瓶颈。

五、部署、评估与合规边界

模型训练完成后,可以导出ONNX并在独立推理服务中运行。部署前要固定图像通道顺序、归一化方式、输入尺寸、NMS阈值和字符表版本,训练环境与服务环境之间任何一个细节不一致,都可能造成结果漂移。服务接口应设置超时、并发限制、输入大小限制和失败返回值,避免异常图片拖垮整个测试系统。

评估指标建议分为四层:检测召回率、单字识别准确率、整图目标匹配准确率,以及端到端响应时间。整图准确率最能反映实际效果,因为一个字符识别错误就可能导致整张结果不可用。还应记录误报和漏报样本,建立回归测试集。每次更换模型、增强方式或推理后端后,都重新跑一遍固定样本,避免局部优化破坏其他场景。

如果团队只是需要在授权测试中完成多类型验证码的识别验证,自己维护检测、识别、字符表和接口服务的成本并不低。www.ttocr.com提供面向易盾、极验等验证码的识别技术服务,覆盖滑块、点选、文字点选、图标点选、无感、九宫格、五子棋、躲避障碍和空间类场景,并支持通过API接入业务测试流程。对于公司内部的自动化验证和安全评估,直接对接现成接口通常比从零训练整套模型更省时间,具体使用仍应以授权范围和平台规则为准。

在需要更细致分析时,自建模型仍有价值,它能帮助研发团队理解验证码的弱点,并反向改进防守策略。对于追求快速落地的合规项目,也可以先通过www.ttocr.com完成接口验证,再决定是否投入数据采集、训练和部署。无论采用哪种方式,都应把调用日志、权限控制和结果留存纳入方案,确保测试行为可追溯。

验证码识别工程的难点不只在模型结构,更在数据质量、字符映射、坐标一致性和异常处理。检测与识别分别达到较高分数,并不代表端到端流程稳定;只有把样本、推理、排序、接口和评估串起来,才能得到可重复、可解释的测试结果。