卡牌匹配完全体框架操作指南.md 15 KB

卡牌匹配完全体框架 · 操作指南

本目录是「宝可梦卡牌匹配完全体」框架的自包含可迁移包:一张交易平台图(eBay 原图)进来, 输出「匹配到的 card_id + 评级信息 + 三属性(编号/稀有度/元素)+ 入库判定」。 代码/文档/配置资产已在包内;模型权重需按 114模型资源清单.md 用硬盘拷进 models/

生成时间:2026-07-27。深入细节见 docs/ 下各子系统专文,本文只讲全局架构 + 怎么跑


0. 一句话数据流

eBay 原图
  │
  ├─【A】卡牌本体分割(★card_seg_v2, yolo26s-seg) → 4点透视矫正 → 正立 ── 得「正立卡面图」
  │
  ├─【B】双区级联检索(DINOv2-large 上半区召回 + 下半区重排) ─────────→ card_id + fusion/u/l 相似度
  │         (查询图直接裁卡→letterbox→上下半区特征→全库检索)
  │
  ├─【C】语种+方向判断(PaddleOCR 字符统计) ────────────────────────→ language(tcg us/jp/简中/繁中)+angle
  │
  ├─【D】cat16 三属性(正立图):
  │         card_no(yolo26s_card_no检测+PP-OCRv6 rec-only+单次宽容) / rarity(YOLO26s 25类) / element(YOLO26s 13类)
  │
  └─【E】评级卡区域(YOLO26s-seg 12类 → 裁评级框 → PaddleOCR) ───────→ 评级公司/分数/编号/签字分
  │
  ▼
【入库精修算法】合并 A~E → 按规则分流 → 匹配入库结果.xlsx + 人工核验分类图

五个子系统各自独立、可单独跑;入库精修算法ebay_sync/_build_ruhku.py)是把它们串起来做「确定入库 / 人工核验」判定的总闸。


1. 本包目录结构

完整流程/
├── 卡牌匹配完全体框架操作指南.md   ← 本文(总纲)
├── 114模型资源清单.md              ← 模型在114的路径 + 拷贝方法
├── config.py                       ← 全局配置(模型路径已指向 models/)
├── models/                         ← ★需自行拷入(见清单):.pth/.npy/.pt/.onnx/元数据
│
├── modules/                        ← 核心可复用模块
│   ├── yolo_detector.py            #  卡牌检测裁切(onnx)
│   ├── rectifier.py                #  透视矫正 + 旋转正立
│   ├── feature_extractor_dual.py   #  ★双区 DINOv2-large 特征提取(建库/查询共用预处理)
│   ├── vector_index.py             #  向量检索
│   ├── ultralytics_compat.py       #  import_yolo() 规避命名空间遮蔽
│   ├── image_downloader.py / csv_reader.py / db_reader.py
│   └── feature_extractor.py / grading_detector.py   # (A4/card_v1 旧线,保留兼容)
│
├── scripts/
│   ├── cascade_match.py            # ★双区级联(单图/自检索/pairs)
│   ├── cascade_match_batch.py      # ★双区级联批量(目录→csv+topk.json,入库用)
│   └── build_gallery.py / match_transactions.py / test_single.py  # (A4 旧线,参考)
│
├── ocr_judge.py / yolo_crop.py     ← 【C】语种+方向(paddleocr / pytorch)
├── grading_ocr.py / step1_crop.py  ← 【E】评级卡(paddleocr / pytorch)
├── parse_card_no.py                ← 【归档】旧 card_no 五格式规则(勿再作最终 card_no)
│
├── ebay_sync/                      ← 应用侧脚本(cat16三属性 + 入库算法 + ebay批量)
│   ├── _build_ruhku.py             #  ★★入库精修总闸(合并+规则分流+xlsx)
│   ├── _build_ruhku_html.py        #  ★可视化 HTML 生成
│   ├── _run_gm_test.py             #  ★服务器GPU三阶段(评级检测+双区匹配+评级OCR)
│   ├── _step1_param.py / _grading_param.py   #  评级脚本的薄包装(改路径调 main)
│   ├── _run_lang_stage.py / _run_lang_for.py #  ★语种消歧(仅对5.1那批跑OCR)
│   ├── _pull_gallery_for.py        #  拉 gallery 图(带下载校验+重传)
│   ├── run_rectify_only_cat16.py   #  cat16 阶段0:裁卡+矫正+正立→rectified_cards
│   ├── run_infer_from_rectified.py #  cat16 阶段A:裁ROI+rarity/element(card_no 旧 OCR 段已废弃)
│   ├── run_pixel_rarity_rule.py    #  cat16 阶段B:rarity 像素右侧规则(card_no 应改接新链路)
│   ├── _rarity_boxes.py            #  rarity 多框+cx
│   ├── ocr_card_no_step.py / _ocr_with_boxes.py / parse_card_no_ebay.py  # 【归档】旧五格式
│   ├── infer_cat16_pipeline.py / run_full_rerun_cat16.py
│   └── ebay_infer_stream.py / ebay_lang_judge.py / ebay_rematch.py / ...  # ebay批量→ClickHouse
│
├── pokemon/(框架根,不在本包内时指向 wzj 根)
│   ├── flat_card_no_detect.py      #  ★现役 card_no 检测裁剪(yolo26s_card_no conf=0.3)
│   └── flat_card_no_ocr.py         #  ★现役 rec-only + 单次宽容 + 低分置空
│
├── modules/card_no_leniency.py     #  ★现役宽容/格式判定(框架根 modules/)
│
├── assets/
│   ├── roi_box_cat16.json          ← rarity/element 固定 ROI(card_no 不再用)
│   └── grading_roi/                ← 评级卡 10 类 <cls>_roi_box.txt + OCR规则.md + 映射表.md
│
└── docs/                           ← 各子系统专文(深入细节)
    ├── 宝可梦整体流程框架详解.md            (A/B/C 总览)
    ├── 卡牌区域匹配模型架构更新.md          (A + cat16三属性 完整,含 card_no 新链路)
    ├── 卡牌区域OCR内容指南.md              (★card_no 现役总览+合法格式)
    ├── 卡牌区域OCR_rec宽容政策.md          (★card_no 唯一后处理规则)
    ├── 卡牌区域检测裁切与旋转正立流程.md (A 细节)
    ├── 语种判断逻辑说明.md                  (C)
    ├── 评级卡OCR评分提取完整流程.md         (E)
    ├── 卡牌匹配入库算法核心更新点.md        (★入库算法规则 + 1000张结果)
    └── ...

2. 环境准备

两套 互不兼容 的 conda 环境(一台 GPU 机器上都装):

环境 关键依赖 用于
pytorch torch 2.x+cu12x、ultralytics、transformers、numpy、opencv、Pillow A 裁切矫正 / B 双区检索 / D 的 YOLO(含 card_no 检测) / E 的检测裁切
paddleocr paddleocr==3.2.0 + paddlepaddle-gpu==3.2.0、hanzidentifier、pandas、openpyxl C 语种 / E 的评级 OCR
paddleocr37 paddleocr==3.7 + transformers + CPU torch D 的 card_no rec-onlyPP-OCRv6_medium_rec;3.2 环境无法按名加载 v6)

为什么拆环境:ultralyticspaddleocr 底层冲突;v6 rec 还需 3.7 环境。流程仍是「pytorch 出中间产物 → 切 OCR 环境 → 再合并」。

激活:source ~/miniconda3/etc/profile.d/conda.sh && conda activate <env>

GPU 注意:114 是 2×RTX 5090。脚本 _run_gm_test.py 会自动挑空闲显存最多的一块; 若有其他训练占用,各阶段独立进程跑完即释放,峰值仅几 GB。给 cascade_match_batch 不要传 --device 0torch.device("0") 报错),靠 CUDA_VISIBLE_DEVICES 隔离后自动用 cuda。

模型:按 114模型资源清单.md 把权重拷进 models/,用第 4 节自检命令确认齐全。


3. 五大子系统(简述 + 专文指引)

【A】卡牌本体裁切 + 透视矫正 + 旋转正立

modules/yolo_detector.py(CardDetector) + modules/rectifier.py(CardRectifier)。 分割 mask→凸包 4 角点→护栏(valid_quad/has_perspective)→warpPerspective 拉正→按 OCR angle 正立。 → 产「正立卡面图」,是 D、C 的输入。细节见 docs/卡牌区域检测裁切与旋转正立流程.md

【B】双区级联检索匹配 ★核心

scripts/cascade_match.py(类 DualCascadeMatcher) + modules/feature_extractor_dual.py。 查询图→裁卡→letterbox 392→上半区[0:196] dinov2-large→CLS 1024维→L2→全库点积召回 Top-K(CASCADE_TOP_K_RECALL=30) → 下半区[196:392] Layer3→对候选算相似度→fusion=α·upper+(1-α)·lower(CASCADE_ALPHA=0.5)重排→Top-1 card_id。

  • 单图/自检索/版本消歧:python scripts/cascade_match.py --self-test 500 / --image <图> / --pairs <json>
  • 批量(入库用):python scripts/cascade_match_batch.py --image-dir <目录> --out-csv <csv> --top-n 5 → 出 <csv> + <csv基名>.topk.json(每候选带 fusion/upper/lower/master_card_no/language/card_name/series/img_filename)
  • 建库/查询必须同模型同预处理(feature_extractor_dual)。细节见 docs/宝可梦整体流程框架详解.md §三

【C】语种 + 方向判断

yolo_crop.py(pytorch 裁卡) → ocr_judge.py(paddleocr)。字符统计:假名≥10→tcg jp;cjk*3>latin→简/繁中(hanzidentifier);否则→tcg us。顺带出 angle(0/90/180/270)。细节见 docs/语种判断逻辑说明.md

【D】cat16 三属性(card_no / rarity / element)

  • card_no(★2026-08-11 现役):正立全图 → yolo26s_card_no(conf=0.3,多框取最高 conf)→ 裁剪 → PP-OCRv6_medium_rec仅 rec)→ modules/card_no_leniency.py 单次宽容 → 低分不合规置空。
    脚本:pokemon/flat_card_no_detect.py + pokemon/flat_card_no_ocr.py
    文档:docs/卡牌区域OCR内容指南.md + docs/卡牌区域OCR_rec宽容政策.md
    空结果:无编号(无检测框 / rec 空)vs 模糊不可读(有框但 rec_score≤0.9 且格式不合规)。
    旧:固定 ROI seq_left/seq_right + det+rec + 五格式猜号 → 归档,勿再作最终 card_no。
  • rarity:固定 ROI seq_left/seq_right + YOLO26s 25 类;像素右侧规则(框中心 x 须在 card_no 检测区域右侧)。
  • element:固定 ROI + YOLO26s 13 类(右上角能量图标)。 驱动:run_rectify_only_cat16.py(阶段0) → rarity/element 既有 Stage A/B;card_no 改接新检测+rec 链路。细节见 docs/卡牌区域匹配模型架构更新.md

【E】评级卡区域识别

step1_crop.py(pytorch, YOLO26s-seg 12类 → 裁评级框+透视拉直) → grading_ocr.py(paddleocr, 按 assets/grading_roi/<cls>_roi_box.txt 分框 OCR → grade_score/grade_name/cert_number/auto_score)。OCR 判「非评级卡」= 误检自动剔除。细节见 docs/评级卡OCR评分提取完整流程.md


4. 入库精修算法 ★★(把 A~E 串成「确定入库 / 人工核验」)

规则权威见 docs/卡牌匹配入库算法核心更新点.md。核心(ebay_sync/_build_ruhku.py):

  • 阈值SIM_HI=0.50(Top1 fusion≥0.5 高置信);<0.5图库需要更新的卡(留空+存原图)。
  • card_no 消歧:默认只用 Top1;当 Top2-5 有候选 fusion 与 Top1 差 ≤CLOSE(0.15) 时触发—— 接近候选(含Top1)里 master_card_no==det_card_no(现役 card_no 链路) 唯一者采纳(确定匹配·编号消歧)。
  • 规则5.1 语种消歧:若 ≥2 候选同号无法定夺 → 对这批query 图跑语种OCR(_run_lang_stage.py,只此分支跑,不全量), 同号候选里只留与 query 同语种者;唯一 → 采纳(确定匹配·语种消歧);仍 ≥2 → 多张卡牌编号相同(留空+存图)。
  • 规则5.2:接近候选无一 card_no 命中 det → 未识别到相应编号(留空+存图)。
  • 评级卡:OCR 判真的 → 原图+评级框另存 评级区域\{原图,评级框};grade/cert 入 xlsx。
  • rarity/element 入 xlsx,不进 cards_master_v2
  • 留空语义:需人工核验的行,其 identity 字段(final_card_id/卡名/系列/语种/年份)留空(= 未确定正确匹配)。

输出根ebay_入库\人工核验\匹配入库结果.xlsx + 分类图片文件夹 + 可视化\匹配可视化.html)。

1000 张实测(2026-07-27):确定匹配 360 + 编号消歧 294 + 语种消歧 27 = 681(68.2%);图库需更新 122;多张同号 98;未识别 98;评级卡 250。


5. 端到端运行(复现 1000 张联合测试)

前提:models/ 已就位;ebay_sync/ 里脚本内嵌 114 凭据(paramiko),本地 Windows/Python 跑即可。 采样源 test_images_cat16(2000 张,数据集,不在包内;在 114 ebay_sync/test_images_cat16/)。

cd 完整流程\ebay_sync

# ① 服务器GPU三阶段(评级seg检测 + 双区匹配 + 评级OCR),拉回 _gm/n1000/
python _run_gm_test.py 1000 42

# ② 合并+分流(pass1,先出 5.1 的 id 清单)
python _build_ruhku.py "_gm/n1000" "D:\顾工交接\wzj\ebay_入库\人工核验" --ids-only
# ③ 只对 5.1 那批(约125张)判语种
python _run_lang_stage.py "D:\顾工交接\wzj\ebay_入库\人工核验\_multi_cardno_ids.txt" "_gm\n1000\_lang_result.csv"
# ④ 合并+分流(pass2,带语种消歧,出最终 xlsx + 分类图)
python _build_ruhku.py "_gm/n1000" "D:\顾工交接\wzj\ebay_入库\人工核验" --lang "_gm\n1000\_lang_result.csv"

# ⑤ 可视化 HTML(query原图 + Top-5 gallery缩略图 + 评级框 + 判定/语种)
python _pull_gallery_for.py "_gm/n1000/match_result.topk.json" "D:\顾工交接\wzj\ebay_入库\人工核验\可视化\gallery"
python _build_ruhku_html.py "_gm/n1000" "D:\顾工交接\wzj\ebay_入库\人工核验\可视化"

cat16 三属性本测试直接复用 data_all/卡牌区域/infer_cat16_result_2000.xlsx(1000⊂2000)。 若换新图集,需先跑 §3【D】的三阶段生成三属性,再进 _build_ruhku.py。 ⚠ 写 xlsx 前先关掉 Excel 里的 匹配入库结果.xlsx(文件锁)。

单独跑某子系统见对应专文;只想验证双区检索通不通:python scripts/cascade_match.py --self-test 200


6. 关键脚本速查

想做的事 脚本 环境
双区自检索 sanity scripts/cascade_match.py --self-test N pytorch
交易图批量匹配→card_id scripts/cascade_match_batch.py pytorch
评级检测+裁框 step1_crop.py(或 ebay_sync/_step1_param.py 包装) pytorch
评级 OCR 提分 grading_ocr.py(或 _grading_param.py paddleocr
语种判定 ocr_judge.py / 入库用 ebay_sync/_run_lang_for.py paddleocr
cat16 三属性(生产) ebay_sync/run_pixel_rarity_rule.py pytorch+paddleocr
入库合并+分流 ebay_sync/_build_ruhku.py 本地(纯python)
联合测试三阶段 ebay_sync/_run_gm_test.py 本地→114 GPU
可视化 ebay_sync/_build_ruhku_html.py 本地

7. 已知局限 / 待办

  • 匹配 Top1 对「同角色不同印刷版本」偶混淆——正是下半区 Layer3 + card_no/语种消歧要补的;仍有 ~10% 进「多张同号/未识别」需人工。
  • rarity 训练样本不足,偶有误检;评级 12 类外的评级公司(GEM/HGA 等)会漏检(归 Other)。
  • match_transactions.py(A4 单区)已被 cascade_match_batch.py(双区)取代,仅留作参考。
  • 大模型/HF缓存需按 114模型资源清单.md 手工拷入 models/
  • 语种消歧只在 5.1 分支触发(省推理);如需全量语种,另跑 §3【C】。