摘要

在《魔法门之英雄无敌:上古纪元》的战斗中,生物受到法术、英雄技能或自身能力影响时,它的属性面板(生物面板)右下角会出现一排圆形小图标,每个图标角上有一个小数字或 ∞ 符号(下文称“角标”)。鼠标悬停在图标上时,会弹出说明文字,例如“寒霜刺骨:受到的魔法伤害提升 50%”。

本实验(编号 B035)想让程序自动读出这些信息。2026-09-10 到 09-21 间分多轮推进,做成了三件事,也明确留下了一个大缺口:

  • 找图标位置:一套像素规则(亮圆环 + 周围暗底)在固定参考上 132 个图标框匹配 131 个,额外误框 0。
  • 读角标:把角标裁出来交给本地视觉语言 OCR 模型重读,普通数字大多能读对,但 ∞ 始终被读成 00 或 8;后来改用“横向两个孔”的像素字形规则,既有 8 个 ∞ 全部找到,118 个数字和 448 个空槽没有误报。
  • 读悬浮说明:自动定位说明框并局部重读,在同一份 26 字段稀疏参考上精确 26 个(但这只是开发参考)。
  • 没做到:图标对应哪种效果(规范身份)、角标数字是不是“剩余回合”、属于哪个单位实例、跨帧跟踪,全部仍未验证。

所有数字都来自已经看过的开发录像,参考由助手目视记录且待用户确认,不是独立准确率。

要回答的问题

  1. 能否在截图里自动找到生物面板上的状态图标?
  2. 能否读出图标角标的原始字面(数字或 ∞)?
  3. 能否读出悬浮说明的标题与正文?
  4. 这些信息能否进一步变成“某个单位身上有某效果、还剩几回合”?

前三问是“观察”,第四问是“解释”。项目坚持把它们分开:读到角标 6 只是字面,不等于“剩余 6 回合”。

数据与来源

  • 安装资源调研(09-10):游戏安装包配置里有 420 条状态(buff)配置、419 个不同 ID、196 个非空图标资源键(游戏版本 0.80.49)。这说明“图标→效果”的映射在资源里存在,但多个效果或等级可以共用一个图标;资源键存在也不代表图标像素已提取。规范映射归知识库模块所有,本实验不复制。
  • 参考数据(截至 09-21):八份参考文件,114 条帧记录对应 113 个原图路径、174 个图标框记录。它们不是 174 种效果,也不是 113 个独立事件(含空行、半透明画面、同一次悬停的相邻帧)。
  • 已见过的悬浮说明:九种标题,例如注能盔甲(防御力提升 5,速度提升 1)、阿丽娜之触(先攻值提升 2,生命值上限提升 20%)、寒霜刺骨(受到的魔法伤害提升 50%)、厚皮(受到的近战伤害减少 30%)。这些是截图上的文字转录,不是经过核实的通用规则,也可能来自法术、英雄或能力。
  • 所有截图都来自已用过的开发录像;两段预留做验收的录像从未打开。

方法

1. 悬浮说明文字

在自动定位到的生物面板右下区域,寻找金色标题、对齐的正文和暗色背景,生成“标题”“正文”两个文字字段。第一版只保留含汉字的正文行,结果把“阿丽娜之触”末行的 20%。 丢了,输出了截断的错误正文;第二版保留数字行,该字段改为“分数不足而拒识”——修复的是“错误接受→明确拒识”,不是读对了。之后对自动框做局部裁图,交给本地 PaddleOCR-VL-1.6 模型重读(原尺寸一遍、补边后放大 4 倍一遍,两种结果都保留,不按参考挑赢家)。

2. 状态行图标定位

先按协议冻结规则:从自动生物面板平移出一排最多 9 个槽位,在每个槽位找“金色圆环”。第一版在 88 张图上一个都没找到——联系图显示位置大致对,但外圈其实偏灰绿,不是金色。失败输出保留后,回到两张设计用原图分析亮度,改为第二版:圆环亮度足够、八个扇区大多有亮点、下方外围仍暗(用来排除只有上半圈被底座照亮的空槽)。项目明确说明第二版是失败后的开发修订,不冒充原协议成功。

3. 角标读取

对每个找到的图标,裁出角标区域,用三种方式读:整屏 OCR、局部 VL 原尺寸、局部 VL 放大 4 倍。只接受完整的 1–3 位数字或 ∞,不按游戏知识纠字,不把 00/8 改写成 ∞。

4. ∞ 字形规则

既然 OCR 换模型、换预处理都读不对 ∞,就直接看像素形状:∞ 矮而宽、两个孔横向排列;8 高而窄、孔竖向排列。规则只接收 44×35 的原尺寸角标裁图,在三个亮度阈值下提取灰白笔画,要求单个连通图形、尺寸与位置合理、恰好两个横向排列的孔,至少两个阈值通过才输出 ∞,否则拒识。不闭合缺口、不补笔画。

5. 局部状态行质量

原来整块生物面板有一个“外观质量门”(左侧区域暗蓝像素占比需 ≥ 0.85),用来拒绝淡入或半透明画面。但技能提示遮住面板左侧时,右下状态行其实仍可读,却被整体拒掉。第二版补充路径:只在左区质量失败、且有唯一自动父面板时,单独检查角标那一条的暗背景(暗像素占比 ≥ 0.90),通过后再用原圆环规则;左侧攻防字段不因此放行。第一版取样带误落在面板底边装饰上,0 个图标,失败保留。

设置

  • 匹配标准:图标框与参考框一对一、重叠度 IoU ≥ 0.5。
  • 只有被参考明确标为“整行穷尽”的帧,才把未占用槽位当作空槽负例;未标注区域不当空白。
  • 推理从不读取参考;评分在预测冻结之后单独运行。

结果

状态行图标定位(5 张首批参考,27 个图标,18 个空槽)

方法 正确框 误框 漏框
每张固定 9 槽全部当图标 27 18 0
亮圆环 + 暗背景(第二版) 27 0 0

之后在更多来源上冻结同一规则复跑:跨来源 23 张(12 图标、18 张空条)12 个全对、0 误框;补样 32 张(63 图标)63 个匹配、0 漏框、0 多框。

角标读取(首批 27 个角标)

读法 精确 错误 拒识
整屏 OCR 12 0 15
局部 VL 原尺寸 26 1 0
局部 VL 放大 4 倍 24 2 1

唯一的原尺寸错误是把 ∞ 读成 00。补样 32 张中 61 个可读角标:整屏 42 精确,局部原尺寸 60 精确,放大 59 精确。

∞ 专项(新 14 张参考,28 个角标,含 7 个 ∞):上游找到 26 个图标(另 2 个因父面板没定位而漏)。六种局部读法(VL 三种预处理、PP-OCR 三种预处理,共 156 次读取)中,普通数字基本读对,7 个 ∞ 在所有读法下都没读对;灰度放大只能把错误变成拒识。

∞ 字形规则(五批既有输出,805 张图、882 个槽位检查)

参考组 ∞ 找到 数字误报 空槽误报
设计用录像 5/5 0/12 0/46
其他已曝光录像 2/2 0/7 0/36
补样批 — 0/61 0/171
跨来源两批 — 0/12 0/195
首批五张 1/1 0/26 —
合计 8/8 0/118 0/448

另有 2 个被鼠标遮住的角标全部拒识,不算判对。

局部状态行质量(984 张图,76 张参考帧、132 个图标)

方案 匹配 漏框 全部候选
原整面板规则 128 4 333
局部第一版(失败) 0 132 0
去掉外观门的诊断版 121 11 326
保留旧路径的局部补充 131 1 336

悬浮说明(13 张正例、26 个标题/正文字段):整屏所有切块严格比较 10 精确;完整覆盖切块 20 精确;局部 VL 20 精确——剩下 6 个字段在 3 张图上被上游场景判断直接跳过。之后场景入口放宽(另一实验)后,局部 VL 原尺寸与 4 倍都达到 26/26,6 张明确负例都没有产生状态提示。

新录像分辨率(21 张,其中 12 张是真实 1080p 录屏):正常可读行 18/18 个图标匹配。

失败与负结果

  • 第一版金色圆环规则在 88 张图上 0 检出;局部状态行第一版 0 检出。两个失败输出都保留。
  • 所有 OCR 读法都读不对 ∞,换模型或放大没有用。
  • 补样中出现 I 被当成 1、放大后输出带格式的 \underline{1} 而被严格解析器拒识,这两处没有为了单个例子定制修复。
  • 两个漏检父面板原因不同:一张没有标题锚点、未定位面板;另一张已定位,但左侧提示遮挡使暗蓝占比 0.844,略低于 0.85 被整体拒绝。项目明确不把阈值直接降到 0.84。
  • 半透明面板仍可能被旧外观门放行(例如一张透出战场格子的画面仍输出了图标);局部补充沿用旧路径,修不了这个问题。
  • 去掉外观门的诊断版在半透明图上多出 5 个框,这不是改进。

局限

  • 全部是已曝光开发资料,参考由助手目视且待用户确认,相邻帧和同一次悬停不是独立事件;不能称为独立准确率。
  • 只支持当前 16:9 界面皮肤、单行 9 槽;其他缩放、多行状态、真实的 00 角标都没有实测(00 只有合成单元测试)。
  • 1080p 录像验证的是录制分辨率变化,不是另一种游戏界面缩放设置。
  • 角标、说明文字里的时长、以及“当前剩余回合”三者被分开保存。缺少同一单位、同一效果在回合推进或被“缩短持续时间”效果影响前后的连续画面与日志配对,因此剩余回合语义无法确认。

结论与下一步

位置与字面读取已有可用的离线原型;∞ 问题靠直接看像素形状解决了已知样本。但从“读到字面”到“确认某单位有某效果、还剩几回合”,中间的身份映射、单位绑定和时长语义都还没做。后续路线(记录但未执行):先从九种已见标题中挑少量常见效果核实图标—标题—面板关联;用 10 fps 连续片段补回合推进与时长缩短前后的证据;在受控片段里弄清角标语义;核对安装资源中的图标贴图后再做模板或分类基线;最后才考虑运行时“定位到未知图标→由执行层悬停→读说明→保存待审核配对”的学习回路(Perception 只读像素,不移动鼠标)。