# 卡牌区域 OCR rec 宽容政策 ## 适用范围 适用于 **card_no 检测框裁剪后的 rec-only OCR 后处理**。 检测模型:`yolo26s_card_no`(conf=0.3,多框取最高 conf)。 识别模型:`PP-OCRv6_medium_rec`(仅 rec)。 合法格式清单见:`卡牌区域OCR内容指南.md`。 --- ## 一、单次宽容原则 **所有宽容政策最多只能宽容一项,不能对宽容后的结果继续宽容。** 命中任一条后立即返回,不再套用后续政策。 --- ## 二、宽容政策列表(按执行顺序) ### 1. 末尾稀有度后缀 / 符号剥离 - 完整后缀(长到短):`RRR`/`SSR`/`SAR`/`CHR`/`CSR`/`UR`/`HR`/`SR`/`RR`/`AR`/`MR`/`MA`/`PR`/`TR` - 单符号:`*`、`★`、`$`、`C`(允许前导空格,如 `" C"`、`" SAR"`) - 例:`001/095RR` → `001/095`;`DPBP#299*` → `DPBP#299`;`36/160★` → `36/160` ### 2. 末尾 `-` 补 `P`(新增) - 条件:rec 文本**以 `-` 结尾** - 动作:末尾追加 `P` - 例:`001/SM-` → `001/SM-P` - 说明:检测框偶发裁掉促销码末尾 `P` 时使用;仍只宽容一次 ### 3. 纯数字固定位置 `1`/`7` → `/` 仅限**纯数字**,长度 ≥4: | 位数 | 检查位置(1-based) | 索引(0-based) | |------|---------------------|-----------------| | 7 | 第 4 位 | 3 | | 6 | 第 3 位 | 2 | | 5 | 第 3 位 | 2 | | 4 | 第 2 位 | 1 | | ≤3 | 不采用 | — | - 该位是 `1` 或 `7` 才转换 - 例:`0827202` → `082/202`;`21712` → `21/12`;`1164` → `1/64` - 反例:`168132`(6 位,第 3 位是 `8`)→ 不触发 ### 4. 中间空格去除 - 条件:整串只含数字、空格、至多一个 `/` - 动作:去掉所有空格 - 例:`43/1 10` → `43/110` ### 5. 中间点号转斜杠 - 条件:`纯数字.纯数字` - 动作:`.` → `/` - 例:`208.184` → `208/184` ### 6. `No.` / `mo.` / `Na.` 归一 - `No.`/`NO.`/`Na`/`mo.`/`ma.` + 1~4 位数字 → 统一 `No.数字` - 例:`No 006` → `No.006`;`mo.066` → `No.066`;`Na 128` → `No.128` --- ## 三、低分不合规置空(与“无编号”区分) 在完成**至多一次**宽容后: | 条件 | card_no | empty_reason | 展示归类 blank_type | 含义 | |------|---------|--------------|---------------------|------| | **无** yolo26s_card_no 检测框(conf<0.3) | 空 | `no_detection` | **无编号** | 卡牌本身没有编号 | | 有检测框,但 rec 原文为空 | 空 | `rec_empty` | **无编号**(与上合并) | 裁剪区 rec 无字,视同无编号 | | 有检测框,`rec_score ≤ 0.9`,且宽容后**不符合**指南合法格式 | 空 | `blur_unreadable` | **模糊不可读** | 图片太模糊,无法可靠识字 | | 有检测框,`rec_score > 0.9` | 保留宽容结果 | `null` | (有效) | 高分可信 | | 有检测框,`rec_score ≤ 0.9` 但宽容后**符合**合法格式 | 保留宽容结果 | `null` | (有效) | 低分但形态合法,保留 | 合法格式 = 指南中的老五种 + 补全四项(斜杠两侧 1~5、更长促销码、中点 `·`、长码 ≥3)。 **展示层两类空结果:** - **无编号** = `no_detection` ∪ `rec_empty` - **模糊不可读** = `blur_unreadable` --- ## 四、实现 ```python from modules.card_no_leniency import apply_leniency, finalize_card_no, is_valid_card_no_format # 仅宽容 apply_leniency("001/SM-") # -> "001/SM-P" # 宽容 + 低分置空 finalize_card_no(rec_text, rec_score) # -> {card_no, leniency_applied, empty_reason} ``` --- ## 五、效果示例 | rec 原文 | rec_score | 结果 card_no | empty_reason | 说明 | |----------|-----------|--------------|--------------|------| | `001/SM-` | 0.999 | `001/SM-P` | — | 政策 2 | | `0827202` | 0.95 | `082/202` | — | 政策 3 | | `No 006` | 0.99 | `No.006` | — | 政策 6 | | `opponent` | 0.999 | `opponent` | — | 高分保留(框错另议) | | `xyz` | 0.70 | ``(空) | `blur_unreadable` | 低分+不合规 | | ``(空) | 0 | ``(空) | `rec_empty` | rec 无输出 | | (无检测记录) | — | ``(空) | `no_detection` | 本身无编号 |