H.264 去块效应滤波
在编码过程中,为了压缩数据,会对块的变换系数进行量化。
由于每个块是独立处理的,量化误差在块与块之间会产生不连续性。当视频被解码重建后,这些不连续性就会在块的边界上形成明显的方块感,这就是块效应。
去块滤波的目的,就是在解码端对解码后的图像进行平滑处理,以减少或消除这种块效应,从而提高视频的主观和客观质量。
去块滤波是一种环路滤波,意味着滤波后的图像会被用作后续帧的参考图像,这样可以防止块效应在时间上传播和累积。
       Block A               Block B
+---------------------+---------------------+
|                     |                     |
|  Pixel values are   |  Pixel values are   |
|  relatively smooth  |  also smooth here.  |
|      within A.      |      within B.      |
|                     |                     |
+---------------------+---------------------+
                      ^
                      |
                      +-- But at this boundary, a sharp,
                          unnatural transition (artifact)
                          can occur due to independent
                          quantization of A and B.
去块滤波就是要平滑这个边界(^)上的像素值。
工作流程
去块滤波不是对所有边界都进行无脑平滑,而是一个智能和自适应的过程。它主要包含以下几个步骤:
- 
    确定滤波边界:滤波器沿着 4x4 像素块的边界进行。它首先处理一个宏块(16x16)中所有的垂直边界,然后处理所有的水平边界。 - 处理顺序:先垂直,后水平。
- 处理单位:对 4x4 块的边界进行操作。
 A 16x16 Macroblock is composed of 4x4 sub-blocks. Filtering happens on the edges between these 4x4 blocks. +----+----+----+----+ <- Horizontal Edges | | | | | +----+----+----+----+ | | | | | +----+----+----+----+ | | | | | +----+----+----+----+ | | | | | +----+----+----+----+ ^ ^ ^ | | | Vertical Edges
- 
    计算边界强度 (Boundary Strength, BS):编码器会根据边界两侧块的编码信息,为每个 4x4 块边界计算一个从 0 到 4 的 BS 值。BS 值决定了滤波的强度,以及是否需要滤波。 
- 
    滤波决策:根据计算出的 BS 值和边界两侧像素值的差异,决定是否对当前边界执行滤波。 
- 
    选择滤波器类型:如果决定要滤波,会根据像素值的差异和其他条件选择强滤波器或弱滤波器。 
- 
    像素值调整:应用所选的滤波器,修改边界两侧的像素值,使其过渡更平滑。 
边界强度
BS 的计算核心思想是:边界两侧的宏块编码差异越大,越有可能是真正的图像内容边界,而不是块效应,此时滤波强度应该越弱。
BS 的取值和对应的条件如下:
| BS | 条件 | 解释 | 
|---|---|---|
| 4 | 两个宏块中至少有一个是帧内预测宏块,并且边界是宏块边界。 | Intra宏块与邻块差异最大,最容易产生块效应,需要最强的滤波。 | 
| 3 | 两个宏块中至少有一个是帧内预测宏块,但边界不是宏块边界 | Intra 宏块内部的边界也需要较强滤波。 | 
| 2 | 宏块编码参数不同: - 至少一个宏块包含非零的残差。 - 运动向量(MV)不同。 - 参考帧不同。 | 编码参数不同说明块之间存在差异,可能是运动或纹理变化,需要滤波。 | 
| 1 | 宏块编码参数相似,但运动向量差异满足一定条件 | 微小的运动差异也可能引入块效应,需要最弱的滤波。 | 
| 0 | 宏块编码参数完全相同 | 两个块几乎一样,被认为是平坦区域,不需要滤波,以避免图像模糊。 | 
总结一下 BS 的核心逻辑:
- BS = 4(最强): Intra宏块边界。
- BS = 3: Intra宏块内部边界。
- BS = 2: Inter 宏块边界,且内容或运动有显著差异。
- BS = 1: Inter 宏块边界,有微小运动差异。
- BS = 0(不滤波): 两个块编码方式和运动信息完全一致。
滤波决策
在计算出 BS 后,我们就要对边界两侧的像素进行分析。我们以一个垂直边界为例:
      p3 p2 p1 p0 | q0 q1 q2 q3
                  ^
                Boundary
这里 p0, p1, p2, p3 是左边 4x4 块最右侧的一列像素,q0, q1, q2, q3 是右边 4x4 块最左侧的一列像素。
滤波开关决策
首先,如果 BS == 0,则直接跳过,不进行任何滤波。
如果 BS > 0,则需要检查边界是否是硬边界(即真实的图像内容,如物体的轮廓)而不是块效应。这是通过比较像素值的差异和两个阈值 α 和 β 来实现的。
这两个阈值由量化参数决定。QP 越大,量化越粗糙,块效应越严重,因此 α 和 β 的值也越大,允许更强的滤波。
决策条件如下 (以亮度分量为例):
- 计算像素差异:
    - 
        $ p_0 - q_0 < \alpha(QP)$ 
- 
        $ p_1 - p_0 < \beta(QP)$ 
- 
        $ q_1 - q_0 < \beta(QP)$ 
 
- 
        
- 决策:当且仅当以上三个条件同时满足时,才会对这个边界进行滤波。否则,即使 BS > 0,也会被认为是图像自身的纹理或轮廓,跳过滤波以避免模糊。
                        +-----------------+
                        |   Start for an  |
                        |   edge (p, q)   |
                        +-----------------+
                                |
                                v
                      +-------------------+
                      | Calculate BS      |
                      | for this edge     |
                      +-------------------+
                                |
                                v
                        +-----------------+
                        | Is BS > 0 ?     |
                        +-----------------+
                                |
                             No | Yes
            +-------------------+-------------------+
            |                                       |
            v                                       v
    +---------------+                 +--------------------------------+
    |               |                 | |p0-q0|<α AND |p1-p0|<β AND ... |
    |  Do NOT Filter|                 +--------------------------------+
    |               |                                 |
    +---------------+                              No | Yes
                                  +-------------------+-------------------+
                                  |                                       |
                                  v                                       v
                          +---------------+                 +--------------------------------+
                          |               |                 | Check condition for Strong Filter|
                          | Do NOT Filter |                 +--------------------------------+
                          |               |                                 |
                          +---------------+                              No | Yes
                                                        +-------------------+-------------------+
                                                        |                                       |
                                                        v                                       v
                                                  +-----------+                       +-------------+
                                                  | Apply     |                       | Apply       |
                                                  | Weak Filter |                       | Strong Filter|
                                                  +-----------+                       +-------------+
弱滤波
如果决定滤波,对于 BS 为 1, 2, 3 的情况,会使用弱滤波器。弱滤波器只修改边界旁边的少量像素(通常是 p0, q0,有时也包括 p1, q1)。
它的滤波公式比较简单,本质上是基于原始像素值和一个计算出的差值 delta 进行微调。
例如,p0 的新值 p0' 可以表示为:
p0′=clip1(p0+Δ)
其中 Δ 是一个通过 p1, p0, q0, q1 计算出的小修正值。clip1 函数确保结果在 [0, 255] 范围内。
强滤波
当 BS = 4 时,表示这是 Intra 宏块边界,块效应可能最严重,需要最强的滤波。但即使 BS=4,也需要一个额外的条件来触发强滤波:
∣p0−q0∣<(α(QP)≫2)+2
如果这个条件也满足,则执行强滤波。强滤波器会对边界两侧最多各3个像素(p2, p1, p0 和 q0, q1, q2)进行平滑处理,基本上是用一个加权平均值来替代原来的像素值。
例如,p0', p1', p2' 的计算方式(简化版)如下:
p0′=(p2+2p1+2p0+2q0+q1+4)≫3
p1′=(p2+p1+p0+q0+2)≫2
p2′=(2p3+3p2+p1+p0+q0+4)≫3
(q 侧的计算与此对称)。
如果 BS=4 但不满足强滤波条件,则降级为使用上面提到的弱滤波器。