Files
climperor/DESIGN.md
T
vosonandCursor a089660ca9 Drop real template library; keep CDN-only matching.
Remove build_library and runtime artifacts, ignore regenerable outputs, and add README/AGENTS/DESIGN/CHANGELOG for the simplified project.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-26 11:59:48 +08:00

5.8 KiB
Raw Blame History

上分帝(Climperor)—— 方案与实施细节

README.md 是操作手册;本文记录背景、选型与关键决策。协作约束见 AGENTS.md


1. 背景与目标

要解决的问题

在 Dota 2 选将阶段(以及进入游戏后)几秒内自动获取双方 10 个英雄,服务天梯选将辅助或赛后分析。

为什么 GSI 做不到

场景 GSI 可获得的阵容数据
排位 / 普通 All Pick 仅自己的 hero.iddraft 通常为空
Captains Mode 历史上有部分 pick/ban,不稳定
观战 / 裁判视角 阵容字段较全
赛后 需依赖 OpenDota 等外部 API

Valve 已明确关闭普通玩家视角的实时 draft (#9562#7193not planned)。

候选方案

方案 结论
官方 GSI 拿不到双方 pick
Overwolf GEP 备选,偏重
读游戏内存 排除(合规)
截屏 + 模板匹配 选定
整图问多模态大模型 排除为主路径(实测整图几乎全错;裁顶栏后仍不如白名单匹配)

社区同类工具共同点:裁固定 ROI + 模板匹配 / 小模型,输出约束在英雄白名单内。


2. 技术方案

处理流程

截图 → 相对坐标裁 10 格 →(天梯则遮罩段位条)→ CDN NCC 匹配
    → score + margin 双门控 → hero_key | null

关键决策

① 相对坐标

横向 (cx - W/2) / H,纵向与宽高 / H。同宽高比下分辨率无关;21:9 等需锚点或重标定。

② 单一 CDN 模板库

templates/cdn/{hero}.png 来自 Steam 官方头像,按顶栏实际窗口裁切后写入。

曾尝试「CDN 兜底 + real 实拍」双层库。实测修正 CDN 裁切后 CDN-only 即可全对, 继续攒 real 库性价比低,已放弃(见 §3 发现二)。皮肤靠会话策略,不堆变体模板。

③ 宁可不认,不可乱认

  • score >= min_score(默认 0.45
  • margin = Top1 Top2 >= min_margin(默认 0.04

④ 会话层处理皮肤与淡入

  • 选人阶段:多帧确认、允许更高分改判(revise_gain
  • 决策阶段:只补空槽、禁止改判(避免皮肤顶栏覆盖默认脸结论)
  • best 帧优先选人阶段默认脸

3. 关键实测(2026-07-25

环境:2560×1440 无边框;人机 + 天梯。

发现一:CDN 裁切窗口决定上限

初版按正方形取中心,比例与顶栏 111×88 不符,均分约 0.65。 网格搜索得到正确窗口 x0=38, w=182, 全高(源 256×144),均分约 0.94。 写入 fetch_cdn_templates.pyCROP_X0/CROP_X1 后,CDN-only 30/30 / 40/40

兜底层差时先查素材处理,再考虑堆数据。

发现二:不必维护 real 库

CDN-only 开箱即用后,「打几十局攒默认脸」不再是主路径。项目改为只维护 CDN。

发现三:自动标定靠玩家颜色条

10 条固定玩家色定位槽位;中心用中位数槽距拟合(剔除被身后头像污染的宽条); 头像下沿用「格内列 vs 格间空隙」亮度差,勿用逐行差分(易误判到名字行)。

发现四:天梯段位条用遮罩

GSI 不含可靠 lobby 类型时,用右下金色勋章检测(has_ranked_overlay), 匹配时屏蔽底部 32% + 右侧 22%。人机无勋章走全图匹配。

发现五:禁用名单不靠模板

网格按主属性分块 + 客户端本地化名行优先排布;禁用/已选卡片对比度塌陷 (std 约 8–21 vs 正常 ≥33)。heroes.json 需含 attr / name_loc。 格数对不上时 ok=False,不返回残缺名单。

发现六:位置与「我」

定位局位置字用二值 IoU(非 OCR)。「我」优先 GSI team_slot; 否则姓名亮度相对差(最亮比次亮 ≥ 25)兜底。


4. 代码结构

climperor/
├── config.json / heroes.json
├── common.py / recognize.py / draft_session.py
├── gsi_watch.py / gsi_setup.py
├── fetch_cdn_templates.py
├── autocalibrate.py / calibrate.py / capture.py
├── evaluate.py / roles.py / grid.py / modes.py
├── templates/cdn|roles|modes/
└── samples/labels.json          # 评测真值;raw/ 见 .gitignore

运行时目录 preview/results/failures/samples/raw/ 不入库。

主要配置

字段 含义 默认
match.min_score / min_margin 识别门控 0.45 / 0.04
match.ranked_mask 天梯遮罩比例 bottom 0.32, right 0.22
gsi.port 监听端口 3223
gsi.confirm_polls 连续同结果帧数 2
gsi.revise_gain 改判所需分数增益 0.15
gsi.strategy_tail_polls 决策阶段继续视觉轮询 8

5. GSI 自动化

Dota 2 (-gamestateintegration)
  → POST → gsi_watch.py :3223
  → DraftSession 轮询 recognize + roles/grid/modes
  → results/draft_*.json

要点:按 matchid 去重;识别在工作线程;未标定时降级为只截图。

天梯 AP 选人按 2/2/1 成批揭晓,本轮结束前互不可见——因此必须在 HERO_SELECTION 跟踪,不能只在决策时间截一张终局图。


6. 与 dota2-hex

独立验证项目。可选:Rust 重写并入,或本地旁路 HTTP 回传。 合规同 dota2-hex屏幕可见信息 only


7. 参考