摘要
用户的优先级是:先能识别一张手动截取的战斗截图,以后再考虑自动挑选有用的视频帧。本实验没有训练新模型,而是把已经存在的几个模型串成一个“单图读取器”:
- 面板检测器(找英雄属性页、生物属性页、魔法书、战斗日志四类面板);
- 面板内元素检测器(找英雄头像、主技能槽、子技能槽、装备槽、兵栏槽、法术槽);
- 场景、槽位空/有、技能等级分类器;
- 已有的图标身份读取器和法术/子技能匹配器。
输入只有一张原生分辨率截图,输出每个元素的像素框、是否有内容、等级、身份候选,以及按原规则是否“正式接受”。在最新开发来源上:
| 项目 | 结果 |
|---|---|
| 四类面板 | 42 TP / 0 FP / 0 FN |
| 六类元素(IoU ≥ 0.5) | 555 TP / 0 FP / 0 FN |
| 已占用技能槽等级 | 60/60(修复前 57/60) |
| 身份正式接受 | 错误接受 0 个,但很多只能拒判 |
| 热启动单图耗时 | 中位 0.094 秒,p95 0.959 秒 |
这是在已暴露过的开发来源上的结果,不是盲测;没有改动 App 的实际截图流程。
要回答的问题
- 只给一张截图、不给任何场景/框/标签,已有模型组合起来能读出多少界面元素?
- 身份读取能否做到“宁可不答,不要答错”?
- 单图从读文件到输出结果需要多久?
数据与来源
- 复用上一轮实验的划分:45 张校准图、71 张最新开发图。最新 71 张来自 10 月 5 日一个保守归并的来源组里的 5 个对局——已在开发中暴露,不是 5 个独立盲测来源。更早冻结的测试来源和 16 张头像留出集没有打开。
- 标注覆盖“声明的字段”,不是全屏穷尽标注;部分身份真值是助手对照候选与官方图标得出的。
方法
协议在运行新组合前写定:
- 整图找面板:置信度阈值 0.25,同类重叠 > 0.5 的重复框去掉一个。
- 面板内找元素:检测到英雄页或魔法书后,打开该面板已知的原生界面区域,再由元素检测器给框。框不吸附到标注位置。这是固定布局的读取器,不支持任意分辨率;分辨率不对时直接报“不支持”,不缩放硬读。
- 场景/过渡判断只作诊断,不作为整图一票否决。战斗顶部两侧英雄头像由已有的独立 HUD(战斗界面上方的状态条)几何规则提出。屏幕左右不等于敌我归属;玩家资料头像不是英雄。
- 空/有和等级用检测出的裁图判断(而不是真值裁图)。空槽跳过身份推断;“未知是否占用”绝不当成空。
- 身份:区分“身份候选”和“正式接受”。沿用原有接受门槛,不搜索阈值;子技能匹配依赖父技能,若父技能读错会传递错误,这一点照实记录,不偷用真值父技能。
- 计时:从读文件到写出 JSON,模型常驻、CUDA 同步、没有其他视觉 GPU 任务竞争;冷加载单独报告。不含截图热键、App 传输和尚未接入的文字 OCR。
看过错误之后的两项开发修复
初始运行后发现两个问题,修复方案在重跑前冻结:
- 等级角标:初版漏读了 8 个清晰可见的“3”级角标(校准 5、最新 3)。逐个看原图,数字都清楚,问题是框稍有偏移就让旧特征分类器失效。新做法是“白色连通块数字匹配”:只在右下角一半里找接近白色的像素块,按大小过滤后归一化到 20×28,与只从训练裁图学来的数字模板比较余弦相似度;相关度 ≥ 0.80 且与另一等级的差距 ≥ 0.04 才接受,否则保持未知。模板来自 197 个训练槽(2 级 115 个、3 级 82 个);1 级没有训练数据,未验证。
- 槽位角色登记:以检测到的英雄头像为锚点,按已知的 14 个装备格和 7 个兵栏格位置,检查每个检测框中心是否落在某格四分之一格宽以内。不在格上的框移到“未分配元素”里保留,既不删除也不当空槽。这不会挪动或改善原始框,严格定位指标照常计算。
因为删掉多余框会改变后续身份模型的批大小,而低精度(bfloat16)分数在阈值边上可能因此变化,所以修复后又完整重跑了一次 116 张图,而不是只回放保存的输出。
设置
- 每次运行先用 3 张训练帧预热;45 + 71 张全部跑一遍,打分前先保存原始输出。
- 修复版与初版分别保存,不覆盖。之后不再做阈值搜索。
结果
| 指标 | 结果 | 范围 |
|---|---|---|
| 四类面板 | 42 TP / 0 FP / 0 FN | 52 张,含 10 张负例 |
| 六类元素 | 555 TP / 0 FP / 0 FN | 51 张,IoU ≥ 0.5;被提示框遮挡、未审核的魔法书排除 |
| 严格元素 AP50:95 | 0.799915 | 子技能 0.494248,仍弱 |
| 场景 | 68/71 | 仅诊断 |
| 已训练类型的空/有 | 467/467 | 主技能、子技能、装备、法术槽 |
| 兵栏空/有 | 77 个未知 | 没有兵栏空槽模型,不算正确 |
| 已占用技能等级 | 60/60 | 修复前 57/60;校准组 49/49(修复前 44/49) |
| 空装备槽被给出身份 | 0/61 | |
| 玩家资料头像被当成英雄 | 0/10 | 重复头像,范围小 |
身份读取(最新组):
| 类型 | 首选候选正确 | 正式接受且正确 | 错误接受 | 拒判/缺失 |
|---|---|---|---|---|
| 英雄(顶部 10 + 面板 11) | 21/21 | 5 | 0 | 16 |
| 主技能 | 27/27 | 1 | 0 | 26 |
| 装备 | 43/43 | 26 | 0 | 17 |
| 生物 | 35/35 | 0 | 0 | 35 |
| 法术 | 84/84 | 83 | 0 | 1 |
| 子技能 | 最新组无身份真值 | — | — | — |
“首选候选全对”不等于识别完成:按原有门槛,英雄、主技能和生物的大多数仍被拒判。校准组上子技能首选 27/27、接受 21/27;法术首选 48/52,4 个错误首选全部被门槛拒绝——报告最新组 84/84 时不能丢掉这个失败。
计时(修复版,常驻模型):
| 测量 | 数值 |
|---|---|
| 最新组中位 / p95 / 最大 | 0.093724 / 0.958921 / 1.307804 秒 |
| 校准组 p95 | 1.129483 秒 |
| 最新组魔法书图 p95(15 张) | 1.154 秒 |
| 英雄面板图 p95(7 张) | 0.238 秒 |
| 冷加载模型 / 首次预热 | 2.018 / 2.452 秒 |
日志、生物面板图只是便宜地完成了路由,没有真正读文字,所以它们的快不代表内容读完了。
失败与负结果
- 评分口径错误已更正:初版指标把一张明确“未审核、被提示框遮挡”的元素列表当成了空真值,产生 13 个无效误检。更正版只修正这一处范围,不重跑模型;初版基线因此是 555 TP / 3 FP / 0 FN。这 3 个真实误检是一个类似背包物品的框和两个跨半格的兵栏框,修复后的角色登记把它们移入“未分配元素”。原文件全部保留。
- 初版漏读 8 个清晰的 3 级角标,原因是框的小偏移。
- 兵栏没有空槽模型,77 个兵栏槽只能报未知。
- 模块全量测试 7172 通过、2 个已知的导入顺序失败、6 跳过;两个失败与前两次实验相同。
局限
- 修复是“看过错误后的开发修复”,不是新的盲测成绩;最新组是一个已暴露的来源组。
- 固定 2560×1440 布局;1 级技能、兵栏空槽、最新组子技能身份、更多来源和分辨率、严格的小框精度都还没解决。
- 模型分数未校准;候选不是确认身份;没有上线到生产。
- 日志文字、英雄/生物数值、数量、目标预览、选择页内容都没有接进这个单图工具(已有的专门读取器仍存在);App 的“截图→输出”链路没有改动或验证。
结论与下一步
已有模型可以组合成一个能用的单图界面读取器:定位几乎全对、身份不乱接受、热启动 p95 不到 1 秒。但它只覆盖界面元素的位置、空槽、等级和部分身份,大量身份仍拒判,文字和数值字段尚未组合进来。下一步是复用现有的专门读取器补齐文字和数值,并为 1 级技能、兵栏空槽、子技能身份收集数据,再在新来源上测量。
Comments