摘要

战斗记录 App(Battle Notes)一边看玩家打《英雄无敌:上古纪元》,一边截图、识别画面上的数字和图标,再交给状态估计(SE,把读到的观察累积成对局状态和对手构筑的推断)。以前我们只知道“读出来的值大多对”,却不知道实时模式下漏掉了多少画面、读数晚了多久、推断是否因此出错。

本实验取用户 10 月 14 日 23:58 实时玩的一局里录像第 600–780 秒这一段,逐帧做了三层参考答案(金标准):

  • L1 采集:这段时间里出现了哪些值得读的画面(行动条、预览、法术书、生物面板……),App 有没有截到;
  • L2 字段:截到并读出的数字和名称是否正确;
  • L3 SE:SE 由此推出的减员、魔法变化是否正确。

结论很清楚:读出来的值几乎没有错,问题在覆盖和延迟。47 个应采集区间只采到 21 个;唯一的读值错误在战场数量牌;SE 的减员两种排序都对,但魔法净变化只有按画面时间排序时才对。

要回答的问题

  1. 实时模式下,App 漏掉了哪些画面,原因是什么?
  2. 读出来的值错在哪里?
  3. 截图的先后顺序会不会让 SE 产生假的变化?

数据与来源

  • 一段训练录像(10 月 14 日 23:58,用户用安装版 App 实时玩的一局)的录像第 598–782 秒(600–780 秒加前后余量)。用户同意作开发数据,已暴露,是回归基线,不是独立准确率。
  • App 会话目录只读,没有写入。
  • 标注状态为 模型目视核对(MODEL_VISUAL_CHECKED):由 Claude 看解码出的帧来标,不是用户人工审核(REVIEWED)。标注按画面写,不按 App 结果改。
  • 没有跑 OCR 或模型,只用视频解码、看图和现有 SE。

这段里发生的事(录像秒):第 1 回合,602.2 秒我方英雄放连锁闪电(22 魔),天使 12→6,弹到活化盔甲 52→25(当时它是行动条第 14 张卡、屏幕上看不见);605.3 秒再放一个群体法术;之后对手一堆圣骑兵想了 142 秒(608–750),期间用户反复打开法术书、生物面板、英雄页;750.0 秒圣骑兵等待,750.6 秒我方魔法 147→149、敌方 170→168 同时变化;随后又有两堆生物选择等待。英雄攻防法强全段不变。

方法

对齐时钟。 App 记录的“媒体秒”是它自己的实时时钟,和录像时间不完全一样。把会话里第 22–45 张截图和录像前后 2.5 秒内的每一帧比灰度差:7 张有唯一最佳匹配,偏移 0.89–1.31 秒,中位 +1.21 秒(录像秒 = 媒体秒 + 1.21);其余 17 张画面静止、匹配不唯一,但也都落在 0.61–1.32 秒内。相邻两张截图之间就有 0.25 秒差,所以这是逐帧抖动而不是漂移,不确定度按 ±0.35 秒计。

三层标注。 按 2 fps 帧标出每一个“值得读”的区间(例如“一次行动结束后行动条稳定的那几秒”“生物面板打开的那几秒”),以及每个区间里屏上的真实数值;预览和换手处用 5–10 fps 补看。然后把 App 的每个读数放进对应区间判对错,再用保存的 SE 请求重跑 SE 比较推断。

这里用到几个 App 内部概念:

  • 行动条:屏幕底部按出手顺序排的生物卡片,每张卡上有颜色(阵营)和数量。
  • 战场数量牌:战场上每堆生物脚下显示数量的小牌子。
  • 主读取:App 按额度定期取整帧去完整识别;旁路读取:检测到某个特定画面(如行动结束、打开信息页)时单独排队读一张。
  • 主读取额度:一局主读取最多 58 张。

设置

  • SE 输入:会话保存的 SE 请求(268 帧)只保留媒体秒 ≤ 780.79 的 74 帧,分别按原截取顺序和按画面时间顺序各跑一次。
  • 字段判分只对“读出来的牌/字段”判对错;被遮挡没读出的数量牌不算漏读(没有逐格的数量牌真值)。

结果

L1 采集:47 个区间,采到 21 个

类型 区间 主读取读到 旁路读到 采到但没读出 落在时间边界 漏
行动后行动条稳定 5 2 1 1 – 1
攻击/法术预览 3 – 1 – – 2
法术书 14 3 6 – 1 4
生物面板 16 2 3 2 1 8
英雄页 6 2 1 – 1(读到) 2
战斗日志 1 – – 1 – –
其它(英勇攻击提示) 2 – – – – 2

延迟(区间开始 → App 取到那帧 / → 读数存好):

读取 取帧延迟 存好延迟
行动条(3 次) 1.2–4.2 秒 11.1–18.5 秒
预览(1 次) 0.3 秒 43.1 秒(排队 39 秒)
主读取(法术书、面板、英雄页) 0.2–2.3 秒 15.7–48.5 秒
旁路信息页(15 次) 0.2–4.1 秒 117–517 秒

旁路信息页存的帧本身很及时,但要等很久才轮到识别:段内 15 个都是画面出现 114–523 秒后才从队列取出,其中 12 个是在主读取的 58 张额度用完之后才轮到。

漏读原因:6 个生物面板、1 个法术书和 1 个日志区间已经排队,后来因为队列满 16 个而被挤掉;7 个区间没有任何触发;一次行动后没有触发“行动条稳定”事件;两次预览没有触发预览检测。另有一次假触发(敌方回合屏上并无预览),读数被正确拒绝。

L2 字段:读出的值只在战场数量牌上出错

段内 37 个读数(主读取 16、信息页 15、行动条 4、预览 2):

字段 对 错 未读 不计分
HUD 攻/防/法强(两方) 210 0 0
HUD 魔法(两方) 70 0 0
行动条卡数量 116 0 1
行动条卡颜色 117 0 0
行动条卡兵种 63 0 0 54
战场数量牌数量 170 2 5
战场数量牌兵种(身体候选) 94 2 6 68
生物面板 数量/攻/防 15 0 3 个页被拒
预览数字与目标 5 0 0

(HUD 是战场顶部显示双方英雄属性和魔法的条。54 个行动条兵种不计分,是因为这段里没开过对应的生物面板,名称无法独立核对。)另有 26 个读数屏上有行动条但只读了 HUD、没输出卡片,按“未尝试”另记。

全部错值:

  1. 两张截图(632.2 秒、707.1 秒)里,判官的数量牌是 26,读成 126:牌左边的白色标记被当成了“1”。
  2. 一张截图里敌方 31 的牌(实际梅杜莎雕刻家)身体候选给的是妖精巨龙。
  3. 一张截图里我方 46 的牌(实际梅杜莎)身体候选给的是观世者。

2、3 是 App 自己标的第一候选,不是确认值;但 SE 由此另建了三条只有一次读数的假兵种序列。

L3 SE:减员都对,魔法变化取决于排序

按截取顺序 按画面时间顺序
真实减员找到 2/2 2/2
漏减员 / 假减员 / 假回升 0 / 0 / 0 0 / 0 / 0
判官 126 正确地列为可疑读数,不算减员 同左
假兵种序列 3 3
段内魔法净变化行 14 行,只有 4 行是真变化(且重复) 1 行,真
敌方魔法 170→168 找到 2 次(重复) 找到 1 次
魔法来回跳(A→B→A) 25 次 0 次

为什么排序有影响:主读取取的是队列里 15–40 秒前的帧,但按“截取完成”的顺序交给 SE,于是一个旧数字可能排在新数字后面,SE 看到“147→190→147”这类来回跳就会写出假的魔法变化。按画面时间重排后,这段里假变化全部消失。

另外两点:减员区间偏宽(天使的区间从 599.1 到 613.6 秒,因为中间那张天使数量没读出;活化盔甲从约 547 到 609.2 秒,因为它在 602 秒时是看不见的第 14 张卡);147→149 这次真实魔法变化 SE 最早在 759.7 秒那帧看到,比实际晚 9 秒,读数存好又晚 23 秒。

整局按画面时间排序后只剩一次来回跳(137→123→137,在本段之后约 11 分钟),抽看录像确认是真实变化(花了 14 魔又回了 14),不是读错。

失败与负结果

  • 覆盖是主要问题:47 个区间只采到 21 个,生物面板 16 个漏了 8 个。
  • 延迟大:旁路信息页读数存好要 117–517 秒,预览要 43 秒。
  • 战场数量牌有真实错值(126),身体候选会造出假兵种序列。
  • 按截取顺序时 SE 会写出 13 行假的或重复的魔法变化。

局限

  • 只有一局、180 秒,而且是暴露过的开发数据,不是准确率。
  • 区间边界按 2 fps 标(±0.5 秒),主读取帧时间有 ±0.35 秒不确定度;有 3 个区间因此记为“边界”。
  • 6 个兵种名这段没有面板可核,不计分;标签名是参照 App 写的,不能当独立证据。
  • 数量牌只对读出的牌判对错,没有逐格真值,无法统计“该读没读”。
  • 标注是模型目视核对,不是人工审核。

结论与下一步

这把尺子告诉我们:实时模式要优先修的是采集调度(让该读的画面及时被读、不被挤掉),其次才是数量牌的个别读错;SE 的输入必须按画面时间排序。后续的实时节奏回放实验沿用了这套三层评分,并把会话目录、时间偏移等做成参数,默认情况下逐项重现本实验的原结果。