🎬 第六章 音视频压缩编码基础
📄 一句话概括

运动矢量就是【这块像素是从参考帧的哪个位置移过来的】——但要注意,它只是猜了个位置,猜完还得补残差。

📝 本节和前面几节的关系

6.4.2 讲了帧间编码,这一节讲它内部最关键的一个数据结构。

一、运动矢量里装了什么

帧间预测要回答一个问题:当前这个块,在参考帧里对应的是哪一块? 找到之后,只需要记下相对位移(dx, dy)——这就是运动矢量。 所以帧间编码传的不是整块像素,而是一个矢量加一点点残差。

二、找位置这一步叫运动估计

在参考帧里搜索最相似的块,这个过程叫运动估计(ME)。 搜索是有代价的:块越大、搜索范围越大,找得越准但算得越慢。 所以编码器要在【准】与【快】之间取舍——这也是 H.265 编码慢的原因之一。

三、关键:还要补残差

运动矢量只是【猜了个位置】,猜的块和真正想要的块通常不完全一样。 所以还必须把两者的差单独编一份——这就是残差。 完整的表达是:当前块 ≈ 参考块(由矢量指出)+ 残差。 预测得越准,残差越小,后面要编码的东西就越少。

四、为什么它能省这么多

因为自然视频里运动是连续的:镜头平移时,整幅画面都在朝同一方向移。 这种情况下,一个矢量就能描述一大片区域——传输的数据量微乎其微。 反过来,画面剧烈变化或噪点多时,矢量找不到好参考,残差就会变大,码率上升。 所以码率不是一个常数,它随内容在波动——这是理解码率控制的基础。

五、动手 Demo:一个运动矢量里装了什么

运动矢量就是【这块像素是从参考帧的哪个位置移过来的】。

rows = [("起点", "当前块在帧内的位置"),
        ("参考位置", "在参考帧里找到的最相似块位置"),
        ("运动矢量", "两者的相对位移(dx, dy)"),
        ("残差", "两块的像素差,还需要单独编")]
for a, b in rows:
    print("%-8s %s" % (a, b))

实跑输出:

--------------------------------------------------------------------
一个运动矢量里装了什么
--------------------------------------------------------------------

运动矢量就是【这块像素是从参考帧的哪个位置移过来的】。

  元素         含义
  ------------------------------------------
  起点         当前块在帧内的位置
  参考位置     在参考帧里找到的最相似块位置
  运动矢量     两者的相对位移(dx, dy)
  残差         两块的像素差,还需要单独编

  注意最后一行:**运动矢量只是【猜了个位置】,猜完还得补残差。**
  所以帧间编码省的是【整块重传】,不是【完全不传】。

注意最后一行:运动矢量只是【猜了个位置】,猜完还得补残差。 所以帧间编码省的是【整块重传】,不是【完全不传】。

30 秒实验

  1. 拍一段【镜头缓慢平移】与一段【画面剧烈晃动】的视频,各压一次。
  2. 比较两者码率的差异,这就是运动矢量的作用。

常见误区

  1. 以为运动矢量就是【像素的移动】。它是块的位移,不是每个像素的位移。
  2. 以为帧间编码只传矢量。还要传残差,两者缺一不可。
自测三问(点开对答案) 1. 运动矢量描述的是什么? —— 当前块相对于参考帧中对应块的位移(dx, dy)。 2. 为什么帧间编码还要传残差? —— 矢量指的参考块与目标块通常不完全相同,差值必须单独编。 3. 画面剧烈晃动时码率为什么会升高? —— 运动矢量找不到好参考,残差变大,要编的数据变多。

相关笔记