You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

YOLOv5验证码识别:如何从检测结果生成所有可能的候选验证码

YOLOv5验证码重叠检测结果生成全候选序列方案

核心思路是先按字符从左到右的排列顺序,把坐标接近的重叠检测框归为同一字符位置的候选集,再通过笛卡尔积生成所有可能的字符组合,避免硬判x坐标完全相等带来的漏判问题。

具体处理步骤

  • 原始结果解析:先解包YOLOv5输出的嵌套检测列表,把每个检测项的坐标、置信度字段转为浮点型,提前过滤置信度低于阈值的无效误检结果。
  • 排序与位置分组:先把所有有效检测框按x坐标从小到大排序(对应验证码从左到右的字符顺序);设置同位置判定阈值(推荐取所有检测框平均宽度的40%,避免浮点误差影响),把x坐标差小于阈值的检测框归为同一位置的候选集合。
    以给出的检测结果为例,排序后9l(x=0.92)和0l(x=0.93)的x差远小于阈值,会被归为最后一个位置的两个候选,其余三个检测结果各自单独成组,最终得到4个位置组。
  • 候选序列生成:对所有位置组的类别集合计算笛卡尔积,每个位置选一个候选按顺序拼接,就能得到所有可能的验证码序列。如果多个位置同时存在多候选,这个逻辑会自动生成全量排列组合,比如两个位置各有2个候选时,会输出4组可能的结果。

可直接运行的实现代码

import itertools

# 输入原始检测结果
raw_detections = [[
['7l', 0.19, '0.443182', '0.104895', '0.431818', '0.972055'], 
['4l', 0.33, '0.534091', '0.104895', '0.431818', '0.965045'], 
['5l', 0.6, '0.238636', '0.118881', '0.431818', '0.974508'], 
['9l', 0.92, '0.659091', '0.104895', '0.409091', '0.879532'], 
['0l', 0.93, '0.659091', '0.0979021', '0.363636', '0.651053']
]][0]

# 配置参数
conf_threshold = 0.5  # 低置信度过滤阈值
same_pos_threshold_ratio = 0.4  # 同位置判定阈值占平均字符宽度的比例

# 1. 格式转换+低置信度过滤
valid_dets = []
for det in raw_detections:
    cls_name = det[0]
    x_center = float(det[1])
    box_width = float(det[3])
    confidence = float(det[-1])
    if confidence >= conf_threshold:
        valid_dets.append({
            "cls": cls_name,
            "x": x_center,
            "w": box_width,
            "conf": confidence
        })

# 2. 按x坐标从左到右排序
valid_dets.sort(key=lambda item: item["x"])

# 3. 计算同位置判定阈值
avg_char_width = sum(d["w"] for d in valid_dets) / len(valid_dets)
same_pos_thresh = avg_char_width * same_pos_threshold_ratio

# 4. 按位置分组
pos_groups = []
for d in valid_dets:
    if not pos_groups:
        pos_groups.append([d])
        continue
    # 和最后一组的基准x坐标比较
    last_group_base_x = pos_groups[-1][0]["x"]
    if abs(d["x"] - last_group_base_x) < same_pos_thresh:
        pos_groups[-1].append(d)
    else:
        pos_groups.append([d])

# 每个组内按置信度从高到低排序,提取类别列表
group_cls_list = []
for group in pos_groups:
    group_sorted = sorted(group, key=lambda x: -x["conf"])
    group_cls_list.append([item["cls"] for item in group_sorted])

# 5. 笛卡尔积生成所有候选序列
candidate_sequences = []
for seq in itertools.product(*group_cls_list):
    candidate_sequences.append(" ".join(seq))

# 输出结果
print(candidate_sequences)

运行上述代码会直接输出目标结果:

['7l 4l 5l 9l', '7l 4l 5l 0l']

优化提示

  • 不要用x坐标完全相等作为同位置判定标准,预测框坐标会存在微小浮点偏移,基于相对宽度的阈值判定鲁棒性更强
  • 生成候选序列后,可以计算每个序列的总置信度(序列内所有字符置信度的乘积),取总置信度最高的序列作为最终识别结果,能进一步提升识别准确率
  • 可以根据自己的测试集效果调整置信度阈值、同位置判定比例,减少无意义的候选序列数量

内容的提问来源于stack exchange,提问作者Jake Jin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 15:54:15