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

172 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 上分帝(Climperor)—— 方案与实施细节
`README.md` 是操作手册;本文记录背景、选型与关键决策。协作约束见 `AGENTS.md`
---
## 1. 背景与目标
### 要解决的问题
在 Dota 2 选将阶段(以及进入游戏后)**几秒内自动获取双方 10 个英雄**,服务天梯选将辅助或赛后分析。
### 为什么 GSI 做不到
| 场景 | GSI 可获得的阵容数据 |
|------|---------------------|
| 排位 / 普通 All Pick | 仅自己的 `hero.id``draft` 通常为空 |
| Captains Mode | 历史上有部分 pick/ban,不稳定 |
| 观战 / 裁判视角 | 阵容字段较全 |
| 赛后 | 需依赖 OpenDota 等外部 API |
Valve 已明确关闭普通玩家视角的实时 draft
[#9562](https://github.com/ValveSoftware/Dota2-Gameplay/issues/9562)、
[#7193](https://github.com/ValveSoftware/Dota2-Gameplay/issues/7193)not 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.py``CROP_X0/CROP_X1` 后,**CDN-only 30/30 / 40/40**。
> 兜底层差时先查素材处理,再考虑堆数据。
### 发现二:不必维护 real 库
CDN-only 开箱即用后,「打几十局攒默认脸」不再是主路径。项目改为只维护 CDN。
### 发现三:自动标定靠玩家颜色条
10 条固定玩家色定位槽位;中心用中位数槽距拟合(剔除被身后头像污染的宽条);
头像下沿用「格内列 vs 格间空隙」亮度差,勿用逐行差分(易误判到名字行)。
### 发现四:天梯段位条用遮罩
GSI 不含可靠 lobby 类型时,用右下金色勋章检测(`has_ranked_overlay`),
匹配时屏蔽底部 32% + 右侧 22%。人机无勋章走全图匹配。
### 发现五:禁用名单不靠模板
网格按主属性分块 + 客户端本地化名行优先排布;禁用/已选卡片对比度塌陷
std 约 821 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. 参考
- [Valve #9562](https://github.com/ValveSoftware/Dota2-Gameplay/issues/9562)
- [Valve #14915](https://github.com/ValveSoftware/Dota2-Gameplay/issues/14915)(开发者 OCR ≈85%
- [Overwolf Dota 2 GEP](https://dev.overwolf.com/ow-native/live-game-data-gep/supported-games/dota-2/)
- Steam CDN`https://cdn.cloudflare.steamstatic.com/apps/dota2/images/dota_react/heroes/{key}.png`