本目录是「宝可梦卡牌匹配完全体」框架的自包含可迁移包:一张交易平台图(eBay 原图)进来, 输出「匹配到的 card_id + 评级信息 + 三属性(编号/稀有度/元素)+ 入库判定」。 代码/文档/配置资产已在包内;模型权重需按
114模型资源清单.md用硬盘拷进models/。生成时间:2026-07-27。深入细节见
docs/下各子系统专文,本文只讲全局架构 + 怎么跑。
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)是把它们串起来做「确定入库 / 人工核验」判定的总闸。
完整流程/
├── 卡牌匹配完全体框架操作指南.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张结果)
└── ...
两套 互不兼容 的 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-only(PP-OCRv6_medium_rec;3.2 环境无法按名加载 v6) |
为什么拆环境:
ultralytics与paddleocr底层冲突;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 0
(torch.device("0") 报错),靠 CUDA_VISIBLE_DEVICES 隔离后自动用 cuda。
模型:按 114模型资源清单.md 把权重拷进 models/,用第 4 节自检命令确认齐全。
modules/yolo_detector.py(CardDetector) + modules/rectifier.py(CardRectifier)。
分割 mask→凸包 4 角点→护栏(valid_quad/has_perspective)→warpPerspective 拉正→按 OCR angle 正立。
→ 产「正立卡面图」,是 D、C 的输入。细节见 docs/卡牌区域检测裁切与旋转正立流程.md。
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)docs/宝可梦整体流程框架详解.md §三。yolo_crop.py(pytorch 裁卡) → ocr_judge.py(paddleocr)。字符统计:假名≥10→tcg jp;cjk*3>latin→简/繁中(hanzidentifier);否则→tcg us。顺带出 angle(0/90/180/270)。细节见 docs/语种判断逻辑说明.md。
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。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。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。
规则权威见 docs/卡牌匹配入库算法核心更新点.md。核心(ebay_sync/_build_ruhku.py):
SIM_HI=0.50(Top1 fusion≥0.5 高置信);<0.5 → 图库需要更新的卡(留空+存原图)。≤CLOSE(0.15) 时触发——
接近候选(含Top1)里 master_card_no==det_card_no(现役 card_no 链路) 唯一者采纳(确定匹配·编号消歧)。_run_lang_stage.py,只此分支跑,不全量),
同号候选里只留与 query 同语种者;唯一 → 采纳(确定匹配·语种消歧);仍 ≥2 → 多张卡牌编号相同(留空+存图)。评级区域\{原图,评级框};grade/cert 入 xlsx。输出根:ebay_入库\人工核验\(匹配入库结果.xlsx + 分类图片文件夹 + 可视化\匹配可视化.html)。
1000 张实测(2026-07-27):确定匹配 360 + 编号消歧 294 + 语种消歧 27 = 681(68.2%);图库需更新 122;多张同号 98;未识别 98;评级卡 250。
前提:
models/已就位;ebay_sync/里脚本内嵌 114 凭据(paramiko),本地 Windows/Python 跑即可。 采样源test_images_cat16(2000 张,数据集,不在包内;在 114ebay_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。
| 想做的事 | 脚本 | 环境 |
|---|---|---|
| 双区自检索 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 |
本地 |
match_transactions.py(A4 单区)已被 cascade_match_batch.py(双区)取代,仅留作参考。114模型资源清单.md 手工拷入 models/。