Deblocking Filter的作用
Deblocking与SAO都是HEVC中的环路滤波器,重建图像会首先经过Deblocking,再进行SAO。Deblocking主要用来去除编码的块效应,SAO消除图像的振铃效应。
块效应(block artifact)
我们知道现在的主流编码器都是使用基于块的混合编码框架,以编码块为单位进行预测、变换、量化。
这就导致不同的编码块会使用不同的编码参数,进而不同编码重建块之间的存在一定的差异,尤其在编码块边界处较为明显。
编码块边界处不连续的现象就是块效应。
这种现象在QP较大时比较明显,因此QP越大Deblocking的强度也越大。块效应如下图所示:
滤波边界判决
滤波位置
在HEVC中,滤波只对横坐标或纵坐标位于8像素的整数倍处的边界进行,所谓边界即是CU、PU或TU的交界处。
滤波顺序
在一幅图像中,首先对竖直的边界进行滤波,之后在对水平的边界进行。如下图:
图中每个网格大小都是8x8,首先会从左至右进行实线边界的滤波(如果是边界的话),接下来会从上至下进行虚线边界的滤波(如果是边界)。
在HEVC中,竖直的边界之间滤波互不影响,因此可以同时进行。对于水平边界同理。
边界强度(Boundary strength, Bs)
一个边界是否需要滤波需要看它的边界强度。主要是通过相邻的块的编码信息来判断,如预测模式或运动矢量。Bs的取值由下表得到:
可以看到:
- 当两个相邻块有一个以上的帧内预测块时,Bs=2
- 当两个相邻块有一个以上的非零变换系数块时,Bs=1
- 当两个相邻块的运动矢量差值绝对值大于一个色度分量像素时,Bs =1
- 当两个相邻块参考不同图像时,Bs =1
- 其余情况Bs=0
即我们认为相邻块的预测模式、运动矢量、变换系数差异越大时,它们的边界就越明显。
对于亮度度分量,只有当Bs>0才会应用Deblocking,而对于色度分量,只有Bs>1才会应用Deblocking
此外,对于亮度分量而言,边界两边的像素如何进行Deblocking需要进一步判断,而对于色度分量,两边则相同,不用进一步判断。
Bs获取的流程如下图,其中P,Q代表两个相邻的块
Deblocking以4x4像素块为基本单位进行,如下图,对于竖直边界而言,每次进行Deblocking的像素为其两侧的两个4x4像素块。
计算出当前边界的Bs后,如果Bs满足条件,还需要进一步判断边界两侧的像素是否满足下式:
其中beta跟量化参数有关,可以查表得到,不用关注。其余的p和q对应上图中的像素值。这个式子就在说虽然两个块的差异较为明显,中间有一条边界,但是两个块内部应该是比较平坦的,内部差异较小,这样才是我们想要滤波的情况。
滤波强度
HEVC中有两种滤波模式:强滤波、一般滤波。确定当前边界要滤波后还要判断是要进行强滤波还是一般滤波。
滤波强度不要和边界强度搞混了。边界强度Bs是告诉你这里有没有边界,滤波强度则是来判断边界是不是很明显,需不需要狠狠地滤一波。
是否进行强滤波由下面3个式子判断:
其中Tc也是查表得到的。i=0,3 也就是说要判断4x4块中的第1行和第4行是否满足这三个式子,都满足就进行强滤波。
整体的流程图如下:
接下来介绍一般滤波和强滤波怎么做
一般滤波
对于一般滤波,有可能改变一个像素值,也有可能改变两个像素值,需要通过下式来判断:
7.5式用来判断P中改变几个像素值,7.6式用来判断Q中改变几个像素值。如果满足式子则改变两个,否则改变一个。
这两个式子的含义就是说块越平坦也就意味着P和Q的边界越明显,即需要改变的像素也就越多。
两个式子分别对边界的两边进行判断,有可能一边需要改变一个像素,而另一边需要改变两个像素。
对于边界两边两个4x4的块而言,每一行都需要进行上述操作。
除了7.5 与7.6的条件外,还需要满足一个条件才能进行滤波:
其中是查表得到的,这个式子是为了避免斜坡型的纹理被滤波。整体滤波的判断流程如下:
滤波后的像素值由下式得到:
也就是在原始像素的基础上加上偏移值,具体偏移值怎么算的还有一系列式子,这里就不说了。
通过滤波,消除块效应,如下示意图:
强滤波
强滤波通常作用于平坦区域,这些区域的块效应往往更加明显。强滤波每四个像素改变三个像素的值。如下:
Q块也是同理,将式中的p换成q即可。
色度分量的Deblocking
前面说到过,色度分量只有Bs=2时才进行Deblocking。
色度分量的滤波比较简单,只改变每四个像素中的一个,即p0和q0,的值。也不用分强滤波还是一般滤波,边界两侧也都是改变一个像素。
像素值的滤波方式跟式7.7和7.8一样,只不过其中的delta由下式获得:
自适应滤波
前面式子中有两个参数是查表得到的即和 。其实我们可以自己定义他们的值,进而实现对滤波的自适应控制。像HM中就有输入参数可以控制。在PPS中也会有相应的语法元素:tc_offset_div2 和 beta_offset_div2。实际的 $t_c $值就等于 + tc_offset_div2 * 2, 同理。