H264系列十九 去块滤波器

参考
《新一代视频压缩编码标准 毕厚杰 6.11》
【H.264/AVC视频编解码技术详解】二十、H.264的去块滤波算法

一、去块滤波的基本概念
1. 去块滤波的作用

去块滤波器(Deblocking Filter)是视频编解码器中的重要组成部分,其核心作用在于消除编码过程中产生的图像块效应。图像中的块效应主要因为以宏块为基本单元的编码结构而产生。在编码中,每个宏块的子块都会按照既定分割方式进行预测、变换和量化编码,在这个过程中可能导致块效应的因素主要有以下几种:

  • 由于变换和量化编码的运算精度误差导致边界出现不连续;
  • 由于码率设置较低,量化强度较大,或者相邻宏块的量化参数不一致导致重建图像的细节部分产生差异;
  • 由于运动补偿时的参考块位置与当前块位置关系不一致导致重建像素的内容实际上缺乏相关性。

为了解决该问题,在H.264中定义了名为”Deblocking Filter”的像素域的图像滤波算法,以降低块与宏块边界的像素不一致性,提升整体视觉主观体验。

2. 去块滤波器的定义

在H.264的标准文档中,去块滤波器定义在8.7节中。在H.264的以下profile中,去块滤波是必要的组成部分:

  • Baseline, Constrained Baseline, Main, Extended, High, High 10, High 4:2:2, High 4:4:4 Predictive;

在以下profile中,去块滤波器推荐而不强制使用:

  • High 10 Intra, High 4:2:2 Intra, High 4:4:4 Intra, CAVLC 4:4:4 iNTRA;

在H.264帧解码的过程中,去块滤波器在该帧所有宏块的解码像素数据重建完成之后进行。在执行中,该过程按照宏块地址的顺序,对所有的NxN分割模式的宏块的像素块分割边界分别进行,其中不包括整个图像的边界以及被标志值disable_deblocking_filter_idc所禁用的边界。

3.后置滤波器和环路滤波器

在视频编解码器中加入去方块滤波器的方法有两种:后置滤波器和环路滤波器。后置滤波器只处理编码环路外的显示缓冲器中的数据,所以它不是标准化过程中的规范内容,在标准中只是可选项。相反,环路滤波器处理编码环路中的数据。在编码器中,被滤波的图像帧作为后续编码帧运动补偿的参考帧;在解码器中,滤波后的图像输出显示。这要求所有与本标准一致的解码器采用同一个滤波器以与编码器同步。当然如果有必要,解码器也还可以在使用环路滤波器的同时使用后置滤波器。

在编码环路中使用滤波器比后置滤波有几点优点。首先,环路滤波器可以保证不同水平的图像质量。其次,在解码器端没有必要再为滤波器准备额外帧缓存。第三,经验试验已显示环路滤波比后置滤波更能增加视频流的主客观质量,同时有效降低解码器的复杂度。

尽管有以上这些优点,环路滤波器的复杂度还是较高的。即使经过很大努力进行滤波算法的时间优化,去除其中的乘除法,滤波器也轻易地达到解码器计算复杂度的三分之一。

高复杂度的主要原因是滤波器的高度自适应性,它需要对方块边界及样点量化值进行条件判断和处理。这样,在算法的主要内部循环中不可避免地出现条件分支。众所周知,这是很耗时的。另一个高复杂度的原因是 H.264 中编码算法中残差编码的尺寸。对于 4×4 的方块大小及平均在每个方向上滤波 2 个点,这样几乎图像中每个点都要被调入到内存中,要么被修正,要么用来判断边界点是否要被修正。而对 H.263 环路滤波器或任何 MPEG-4/H.263 后置滤波器来说不是这样的,因为它们对 8×8 方块进行操作。

4.假边界
去方块滤波器的作用是去除 H.264 编解码算法带来的方块效应。但是,如果在 DCT 边界上,正好是图像的边界,如家具边等,若不加以判断而误认为是方块效应,则可能造成新的误差。为此,在滤波方块效应时,应该先判断该边界是图像真实边界还是方块效应所形成的边界(假边界)。对真实边界不进行滤波处理,而对假边界则要根据周围图像块的性质和编码方法采用不同强度的滤波。

二、 去块滤波的执行过程

去块滤波对于每一个宏块的亮度和色度分量分别进行。对于宏块的每一个分量,首先进行垂直方向的滤波,然后进行水平方向的滤波。垂直方向的滤波从左向右进行,水平方向的滤波从上向下进行。在水平和垂直两方向上,待滤波的块边沿分为两类:半宏块和1/4宏块的边沿。标准文档中的插图表示如下:


image.png

在上图中,实线表示半宏块的边沿,虚线表示1/4宏块的边沿。对于亮度/色度以及不同的参数设置,去块滤波操作的边沿不同。对于亮度分量,根据transform_size_8x8_flag的值判断:

  • 如果transform_size_8x8_flag为0,即采用4×4尺寸变换,对实线和虚线的边沿进行滤波;
  • 如果transform_size_8x8_flag为1,即采用8×8尺寸变换,只对实线的块边沿进行滤波;

对于色度分量,只考虑4:2:0格式,只对半宏块边沿即实线部分进行滤波。

宏块去块滤波的过程主要分为如下几个步骤:

  1. 确定当前宏块的邻域有效性;

  2. 获取几个关键的标识参数:

    • fieldMbInFrameFlag:只考虑帧编码,该值应为0;
    • filterInternalEdgesFlag:如果当前slice中的disable_deblocking_filter_idc的值设为0,则该flag为1;反之为0;
    • filterLeftMbEdgeFlag:如果当前slice中的disable_deblocking_filter_idc设为1,或disable_deblocking_filter_idc设为2而且该宏块不可得,或宏块为图像的左侧边沿宏块,则该flag设为0;反之设为1;
    • filterTopMbEdgeFlag:如果当前slice中的disable_deblocking_filter_idc设为1,或disable_deblocking_filter_idc设为2而且该宏块不可得,或宏块为图像的上方边沿宏块,则该flag设为0;反之设为1;
  3. 根据上述关键标识参数执行滤波过程。

2.1 左宏块边沿滤波

若标识位filterLeftMbEdgeFlag设为1,根据协议文档中8.7.1节的方法执行宏块亮度分量左侧边沿的滤波。其中chromaEdgeFlag为0,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (0, k)的k取[0,15]。

2.2 上宏块边沿滤波

若标识位filterTopMbEdgeFlag的值为1,宏块亮度分量的上水平边沿进行滤波过程。由于当前设置下MbaffFrameFlag始终为0,因此根据协议文档中8.7.1节的方法执行滤波。相关参数为chromaEdgeFlag为0,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (k,0)的k取[0,15]。

2.3 内部块边沿滤波

当标志位filterInternalEdgesFlag为1时,执行宏块内部块边沿的滤波。内部块边沿的滤波分为水平和垂直两种。

2.3.1 内部垂直块边沿滤波

内部垂直边沿滤波的步骤为:

  1. 如果transform_size_8x8_flag为0,根据协议文档中8.7.1节的方法执行滤波。相关参数为chromaEdgeFlag为0,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (4,k)的k取[0,15]。该步骤即为第一和第二列块相邻边沿的滤波
  2. 根据协议文档中8.7.1节的方法执行滤波,相关参数为chromaEdgeFlag为0,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (8,k)的k取[0,15]。该步骤即为第二和第三列块相邻边沿的滤波
  3. 如果transform_size_8x8_flag为0,根据协议文档中8.7.1节的方法执行滤波。相关参数为chromaEdgeFlag为0,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (12,k)的k取[0,15]。该步骤即为第三和第四列块相邻边沿的滤波

2.3.2 内部水平块边沿滤波

内部水平边沿滤波的步骤为:

  1. 如果transform_size_8x8_flag为0,根据协议文档中8.7.1节的方法执行滤波。相关参数为chromaEdgeFlag为0,verticalEdgeFlag为0,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (k,4)的k取[0,15]。该步骤即为第一和第二行块相邻边沿的滤波
  2. 根据协议文档中8.7.1节的方法执行滤波,相关参数为chromaEdgeFlag为0,verticalEdgeFlag为0,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (k,8)的k取[0,15]。该步骤即为第二和第三行块相邻边沿的滤波
  3. 如果transform_size_8x8_flag为0,根据协议文档中8.7.1节的方法执行滤波。相关参数为chromaEdgeFlag为0,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (k,12)的k取[0,15]。该步骤即为第三和第四行块相邻边沿的滤波

2.4 色度分量的滤波

在图像为彩色图像的情况下,色度部分同样需要进行滤波操作。对于色度分量的滤波,其思路类似于亮度分量。

2.4.1 色度左宏块边沿滤波

如果filterLeftMbEdgeFlag为1时,根据协议文档中8.7.1节的方法执行宏块色度分量左侧边沿的滤波。chromaEdgeFlag为1,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (0, k)的k取[0,7]。

2.4.2 色度上宏块边沿滤波

如果filterTopMbEdgeFlag为1,根据协议文档中8.7.1节的方法执行宏块色度分量上方边沿的滤波。。chromaEdgeFlag为1,verticalEdgeFlag为0,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = ( k,0)的k取[0,7]。

2.4.3 色度分量内部块边沿滤波

色度分量的内部块滤波也分为水平和垂直两个方向,且只有在transform_size_8x8_flag为0时执行。

对于水平方向,根据协议文档中8.7.1节的方法执行滤波,相关参数为chromaEdgeFlag为1,verticalEdgeFlag为0,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (k,4)的k取[0,8]。

对于垂直方向,根据协议文档中8.7.1节的方法执行滤波,相关参数为chromaEdgeFlag为1,verticalEdgeFlag为1,fieldModeInFrameFilteringFlag等于fieldMbInFrameFlag(帧编码模式中始终0),(xEk, yEk) = (4,k)的k取[0,8]。

三、块/宏块边沿滤波方法

滤波每一个块边沿的方法定义于标准协议文档的8.7.1节。所需要的步骤包括:

  1. 确定相关参数:

    • chromaEdgeFlag:表明当前数据属于亮度或色度;
    • iCbCr:色度分量索引;
    • verticalEdgeFlag:水平、垂直方向标志位;
    • fieldModeInFrameFilteringFlag:隔行模式标志位;
    • nE:一个边沿包含的像素数量,亮度为16,色度为8;
  2. 获取原重建块的待滤波像素;

  3. 根据原像素进行滤波;

  4. 修改重建像素值。

3.1 获取原重建块的待滤波像素

对一个块边沿上的某一个像素位置进行滤波时,需要获取该像素位置相邻的8个原像素值作为参考。标准文档中的插图如下:


image.png

上图中的p0和q0代表块边界某个位置左右的相邻像素,根据滤波方向的不同,可能是左右或上下相邻的像素。以水平块边沿滤波为例,采用边界垂直方向的8个相邻像素,如下图所示:


image.png

上图中,红色像素P0和Q0表示边界两侧的相邻像素,其余蓝色像素为滤波所需要的其他相邻像素。

3.2 边界像素滤波

在获取到边界的参考像素后,下一步执行的操作是参考8个像素值进行滤波。滤波过程的具体方法定义在标准的8.7.2节。实现一个边界的滤波需要三大步骤:

  • 计算边界滤波强度;
  • 判断滤波条件;
  • 滤波边界像素;

3.2.1 计算边界滤波强度

边界滤波强度是边界像素滤波时的一个重要的参数,决定了像素点的滤波采取怎样的算法。实现方法定义在标准的8.7.2.1节。边界滤波强度可能的取值有0、1、2、3、4共5个值。其中:

  • 0:表示该边界不需要滤波;
  • 1、2:主要用于帧间编码图像的滤波;
  • 3、4:主要用于帧内编码图像的滤波;

本节中主要以帧内编码为例说明边界滤波强度的计算方法,即滤波强度取3、4的条件。

  • 当滤波边界为宏块边沿,并且边界相邻像素p0和q0都属于帧编码宏块,并且任意一个像素的所属宏块为帧内编码或所属的帧类型为SI或SP时,边界滤波强度为4;
  • 当滤波边界为子块边界,并且边界相邻像素p0和q0都属于帧编码宏块,并且任意一个像素的所属宏块为帧内编码或所属的帧类型为SI或SP时,边界滤波强度为3;
  • 在帧内编码模式中,同时作为宏块边沿和图像边沿的像素,滤波强度为0,不进行滤波。

3.2.2 判断滤波条件

判断滤波条件的方法定义在8.7.2.2节,所需数据包括边界两侧的4个像素值p0/p1/q0/q1,颜色空间分量标志位chromaEdgeFlag,边界滤波强度bS,所属宏块的量化参数QPp/QPq,以及在视频头部读取到的两个语法元素filterOffsetA/filterOffsetB。

首先计算边界相邻像素所属宏块量化参数QP的平均值:

qPav =(qPp +qPq +1)>>1;

计算查表所需要的两个索引值:

indexA = Clip3(0, 51, qPav + filterOffsetA);
indexB = Clip3(0, 51, qPav + filterOffsetB);

根据计算得到的indexA和indexB,通过在表8-16中查找对应的alpha和beta值:


image.png

根据上述计算得到的信息,可以获得滤波判决条件:

filterSamplesFlag=(bS!=0 && Abs(p0 −q0 )<α && Abs(p1 −p0 )<β && Abs(q1 −q0 )<β);

3.2.3 滤波边界像素

针对边界滤波强度不同的像素点,采用的方法也相应不同。滤波过程修改的像素值包括边界两边的相邻像素以及分别向两个方向扩展两个的像素值,即根据边界左右对称的6个相邻像素。

对于滤波强度为4的像素点(即非作为图像边缘的宏块边界),采用如下方法进行滤波:

如果滤波亮度分量,且满足ap <β && Abs(p0 −q0 )<((α>>2)+2)时,边界左侧或上方的三个滤波后像素的计算方法为:

  • p′0 =(p2 +2p1 +2p0 +2*q0 +q1 +4)>>3
  • p′1 =(p2 +p1 +p0 +q0 +2)>>2
  • p′2 =(2p3 +3p2 +p1 +p0 +q0 +4)>>3

右侧或下方的三个滤波后像素的计算方法为:

  • q′0 =(p1 +2p0 +2q0 +2*q1 +q2 +4)>>3
  • q′1 =(p0 +q0 +q1 +q2 +2)>>2
  • q′2 =(2q3 +3q2 +q1 +q0 +p0 +4)>>3

如果滤波色度分量,或者不满足ap <β && Abs(p0 −q0 )<((α>>2)+2)时,边界左侧或上方的三个滤波后像素的计算方法为:

  • p′0 =(2*p1 +p0 +q1 +2)>>2
  • p′1 = p1
  • p′2 = p2

右侧或下方的三个滤波后像素的计算方法为:

  • q′0 =(2*q1 +q0 +p1 +2)>>2
  • q′1 = q1
  • q′2 = q2

对于滤波强度为3的像素点(即内部块边沿),采用的滤波方法略复杂:

首先依据上面获得的indexA和边界滤波强度查表获得C0值,该值由标准文档中的表8-17获得。


image.png

获取参考像素的二级差分值:

ap =Abs(p2 −p0 )
aq =Abs(q2 −q0 )

计算阈值变量tc:

亮度:tC =tC0 +((ap <β)?1:0)+((aq <β)?1:0)
色度:tC =tC0 +1

计算边界相邻像素:

Δ =Clip3(−tC,tC,((((q0 −p0 )<<2)+(p1 −q1 )+4)>>3)) p′0 = Clip1( p0 + Δ )
q′0 = Clip1( q0 − Δ )

对亮度分量,p1/q1的推导方式为:

p′1 =p1 +Clip3(−tC0,tC0,(p2 +((p0 +q0 +1)>>1)−(p1 <<1)) >> 1)
q′1 =q1 +Clip3(−tC0,tC0,(q2 +((p0 +q0 +1)>>1)−(q1 <<1)) >> 1)

其它,p2/q2以及色度分量的p1/q1/p2/q2像素维持原值不变。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容

  • 在目前,无论在各个行只要和视频相关的,我们都可以看见H264相关的身影,H264作为目前使用最广泛的视频压缩标准,...
    DramaScript阅读 21,546评论 7 56
  • 好记性不如烂键盘,持续整理了一下视频里面一些基础的概念。 文件格式 封装格式 视频编解码方式H.26X 系列MPE...
    vedon_fu阅读 2,179评论 0 3
  • FFmpeg X264编码参数 目录 码率控制 1 X264的preset和tune 2 编码延时建议...
    古则阅读 29,665评论 1 15
  • 在每个人的心里 也许都会有个心结 就拥有一片黑色的天空 在一片黑暗之中 什么也摸不到 什么也看不到 想说却发现无法...
    MiCorazon阅读 379评论 0 0
  • 坐火车到威尼斯,出了车站,对岸就是拯救圣母堂,在阳光照耀下和运河的衬托下光耀夺目。看到水上公交1号线码头有人排队,...
    惠茹姐姐阅读 309评论 5 3