🧠 第七章 数据标注
📄 一句话概括

60 帧的合成视频,帧差阈值 6.0 抓出 3 个关键帧(第 0、20、40 帧)。 查询第 30 帧,最佳匹配是第 20 帧,时间误差 10 帧。 比对次数从 60 次降到 3 次,省了 95.0%。

📝 本节和前面几节的关系

上一节做单帧姿态,这一节加一个时间轴。视频检索的核心矛盾很简单:帧太多算不过来,抽少了又不准。

一、视频检索的两种做法

逐帧比对:把每一帧都抽特征,查询时和每一帧算相似度。准,但代价随视频长度线性涨。 一小时 30 帧的视频有 10 万帧。 先抽关键帧:用某种规则挑出少数「有变化」的帧,只在这些帧上比对。快,但时间精度受限。 Demo 走第二条。抽帧规则用的是帧差:相邻两帧的平均像素差超过阈值,就认为画面发生了事件。 帧差法很土,但便宜到几乎不要钱——一遍扫描就够,不需要任何模型。

二、关键帧抓在哪、漏在哪

60 帧里抓出 3 个关键帧:第 0、20、40 帧。 第 20 帧抓到,是因为画面里多了一条绿色横条;第 40 帧抓到,是它消失了。 第 0 帧是起点,我强制放进去的。 注意第 10 帧、第 30 帧这种「东西在动但没出现新东西」的时刻没被抓到——帧差法只认突变,不认渐变。 这是帧差法的第一个毛病:慢速移动、渐变光照,它一律看不见。

三、省 95% 的代价是 10 帧误差

比对次数从 60 次降到 3 次,省 95.0%。这是收益。 代价是时间精度:查询的是第 30 帧,最佳匹配只能是第 20 帧,误差 10 帧。 为什么会偏 10 帧?因为第 30 帧根本不在关键帧里,只能在已有关键帧里找最像的。 更细的现象是:第 40 帧和第 0 帧的相似度完全一样(都是 0.6822)。 因为这两帧的画面本来就一模一样——物体位置按 40 帧循环,回到了起点。 所以「找到最像的帧」不等于「找到对的时间」。这是关键帧方案绕不开的局限。

四、真实系统怎么补这个洞

  1. 多路触发。不光看帧差,镜头切换、物体出现、语音起点都触发关键帧。
  2. 关键帧之间插值。先定位到粗粒度,再在关键帧附近逐帧细找,两级检索。
  3. 用帧差曲线做时间对齐。 把查询片段的帧差序列和视频的帧差序列对齐,这一步能把误差压到几帧以内。 这三条都不复杂,但都得有「时间」这个概念。只用单帧特征做视频检索,注定在时间上粗糙。 这也是为什么视频模型和图像模型的架构不一样——它得显式建时间维度。

五、动手 Demo:视频检索:抽关键帧,再在关键帧里找最像的

造一段 60 帧的 16×16 合成视频(一个小方块横向移动,中间 20 帧多一条绿条); 用相邻帧平均像素差找关键帧;每帧算 8×8 网格平均色当特征; 用第 30 帧加噪当查询,在关键帧里找最像的,比时间和比对次数。

diffs = [0.0] + [float(np.abs(frames[t] - frames[t - 1]).mean())
                  for t in range(1, T)]
keys = [0] + [t for t in range(1, T) if diffs[t] > 6.0]

g = im.reshape(8, 2, 8, 2, 3).mean((1, 3))     # 8×8 网格平均色
v = g.ravel() / np.linalg.norm(g.ravel())

实跑输出:

--------------------------------------------------------------------
视频检索:抽关键帧再算帧特征
--------------------------------------------------------------------
  视频长度                 60 帧(合成,每帧 16×16)
  帧差阈值                 6.0(平均绝对像素差)
  关键帧数                 3
  关键帧位置               0、20、40

  查询:第 30 帧加一点噪声,看能不能在关键帧里找回来。
  关键帧     余弦相似度
  --------------------
  第 20 帧       0.8671
  第 40 帧       0.6822
  第 0 帧        0.6822
  最佳匹配                 第 20 帧
  时间误差                 10 帧

  全帧检索的比对次数       60 次/查询
  关键帧检索的比对次数     3 次/查询
  省下的比例               95.0%
  关键帧的作用就是把比对次数压下来,代价是时间精度:目标落在两个关键帧中间时,只能匹配到内容最像的那个,时间上会偏。
  这里偏了 10 帧,因为第 30 帧根本不在关键帧里,只能退到最近的那个。
  真实系统不会只靠帧差。镜头切换、物体出现、语音起点都会触发关键帧,而且关键帧之间还要插值,把时间精度补回来。

关键帧只有 3 个,位置是 0、20、40。看着少,但这段视频确实只有两次画面突变。 相似度那一列:0.8671(第 20 帧)、0.6822(第 40 帧)、0.6822(第 0 帧)。 后两个数完全一样,因为这两帧画面本来就一样。 所以「并列」这个现象不是代码错,是数据里真的有重复画面。 真实视频里片头片尾循环、静止镜头,都会出现这种情况。 时间误差 10 帧,按 30 帧每秒算就是三分之一秒。做内容检索够用,做精确剪辑不够。

30 秒实验

  1. 把帧差阈值从 6.0 降到 2.0,看关键帧变几个、时间误差降到多少。
  2. 把查询换成第 25 帧,看最佳匹配会不会变成第 20 帧还是第 40 帧。
  3. 想一想:为什么帧差法抓不到慢速移动的物体?

常见误区

  1. 「抽关键帧一定更快更好」——时间精度会掉,得看用途。
  2. 「最像的帧就是对的时刻」——画面重复时,相似度区分不了时间。
  3. 「帧差法能抓到所有变化」——它只认突变,渐变一律漏掉。
自测三问(点开对答案) 1. 关键帧的作用是什么? —— 把比对次数从全帧降到少数几帧,代价是时间精度。 2. 这一节第 0 帧和第 40 帧的相似度为什么完全相同? —— 这两帧画面本来就一样,物体位置按 40 帧循环回到了起点。 3. 真实系统怎么提高视频检索的时间精度? —— 多路触发关键帧、两级检索加插值、用帧差序列做时间对齐。

视频检索之后,下一节回到静态图,但换个问法:找同一种画风。

相关笔记