转自:https://blog.csdn.net/chenzongduozhu/article/details/62891475
1、 SAO的概念
在图像中像素值剧烈变化的边界区,经过编码-解码重建之后通常会出现波纹状的失真现象,这种失真称作振铃效应。振铃效应产生的根本原因在于边界区高频分量在编码过程中丢失。为了减少高频分量的损失,同时不降低编码的效率,HEVC引入了SAO技术,从像素域入手对振铃区域进行补偿。
SAO在流程中的位置,encoder端:
decoder端:
2、基本原理
SAO对重建图像在deblocking之后操作,操作对象为重建完成的一帧,以一个CTB为一个基本单位。SAO所采用的方式主要有三类:边界补偿(BO)、边带补偿(EO)和参数融合(Merge)。
通过PSNR的计算公式可以看到,重构数据和原始YUV之间的差的平方和是决定PSNR的因素。SAO通过分析deblocking后的数据和原始YUV之间的关系来对deblock后的数据进行delta操作,使得尽量接近原始YUV,达到提高PSNR的目的。
一个最基本的想法就是把deblock的重构数据和原始YUV中每一个相同位置的pixel做差值,把这个差值传给decoder,这样可以完全恢复原始 YUV.但是这实际上是不现实的,如果每一个pixel都传输一个offset,这会导致码率会非常的高,达不到压缩的效果。(如同DPCM)
H265在码率和PSNR之间做了一个tradeoff,以较小的码率增加来提高PSNR。
(1)边界补偿
边界补偿通过比较当前像素和相邻像素的大小对当前像素分类。相邻像素的位置分为四种模式:水平、垂直、左上、右上:
当为某个CTB选择使用了上面某种梯度模式后,开始计算该CTB中的当前sample P和相邻2个pixel之间的关系,用edgeIdx表示:
因为edgeIdx的计算是针对deblocking以后的重构图像进行的,encoder和decoder使用相同的方法来计算,因此不需要传输这个信息给decoder,而是可以由decoder自己来计算,这样虽然增加了计算量,但是可以降低码率。
对于edgeIdx 为0的flat area,可以不需要做任何操作。对于1~4,SAO为每一个edgeIdx分配了一个offset,这个offset会add到重构像素中。因为SAO不是为每一个pixel分配一个offset,而是先把pixel进行梯度的计算,并且做edgeIdx的分类,对每一个edgeIdx类分配一个offset(对每一个CTB有4个offset就足够),这样可以减少码率的消耗。另外,为了进一步降低码率,H265 SAO规定对于edgeIdx=1,2这两种情况下,offset值必须是正数;对于edgeIdx=3,4时,offset必须是负数。通过这种强行的要求,符号位可以不进行编码。
(2)边带补偿
带状补偿将像素值强度等级划分为若干个条带,每个条带内的像素拥有相同的补偿值。进行补偿时根据重构像素点所处的条带,选择相应的带状补偿值进行补偿。
SAOencoder把有效的YUV取值范围(0-255 fullRange, 16-235 BT601/709) 平均分为32个band(如下图,如果是0-255,就是每一个band的范围是8,一共分成32个band),通过某些算法(可以通过RDO确定)来选择其中连续的4个band进行补偿,当CTB中的sample的Luma/Chroma处于这4个选定的band中时,需要对这个sample进行补偿(把该band相关的offset值加到sample的值上)。
encoder端如何选择4个band:
从上面这个图中可以看到这个原理:在encoder端会统计当前CTB中的sample的Luma/chroma值,做32band的直方图统计,每一个band中包含的该YUV中的sample求均值,下面举个例子:
比如假设有一个band是31-38,假设该CTB中有3个pixel的值在这个band中,分别为:
32
34
36
这样可以知道原始YUV该CTB中的sample出现在这个band中的均值为(32+34+36)/3= 34;
对deblock后的重构图像同样做这样的处理,也求出该band中的均值,假设为32.
那么可见,deblocking后的重构YUV和原始YUV在该CTB上,并且该band上有均值上的差值为34-32=+2. SAO因此可以分配band offset=+2 到这个band上,在decoder端,为每一个处于该band上的deblocking后的sample值加上2,这样可以保证在该band上出现的重构pixel和原始YUV上的该CTB的该band上的均值是相等的。
对32个band都做这样的处理,最后选择连续4个,offset值最大的band作为最终确定的需要补偿的band。并且起始band值和4个band offset值写到码流中传输给decoder。通过这种band offset的方式,可以把均值差别最大的4个band补偿成均值相等,来拉近原始YUV和重构图像之间的差值。
一个问题:为什么band offset 模式中只是选择4个连续的band?
标准给出的答案是:
1. 在flat area部分,大部分的pixel的取值应该会集中在很少的几个band中,因此使用连续的4个band能够覆盖大部分的pixel。(也就是说如果对flat area的某一个CTB做直方图的话,这个pixel会很集中在很少的几个取值点,因此使用4个连续band可以很好的覆盖.
2. 因为edge offset模式使用了4个offset值,为了不增加码率,band offset也复用了这4个offset值的syntax,这样不需要另外再增加syntax来专门表示band offset。
(3)参数融合
参数融合模式表示某一个CTB,其SAO的参数可以直接使用某个相邻CTB的参数,只需要指定(标识,只需要传送融合标志位即可)是哪个相邻块(左方还是上方)。这样可以进一步降低码率。需要注意的是因为H265引入了TILE/SLICE结构,而tile是并行处理的,另外也不能跨SLICE,因此当前CTB只有和left/TOP CTB处于同一个tile/SLICE时才能共享SAO参数。
需注意,在参数融合模式下,一个CTB的亮度CTB和色度CTB必须都采用融合相邻块(左或上)的参数。否则如果亮度和色度没同时采用某相邻块的参数,则是非融合模式。采用非参数融合,即亮度和色度分量独立根据自身像素值特点选择划分模式及补偿值,在这种情况下两个色度分量共用相同的划分模式。
3、SAO的意义
SAO是一在deblocking后的一个后处理步骤,会影响到inter prediction的参考帧值。SAO是对重构像素进行了PSNR提升的一个重要步骤,直接对luma/chroma值进行非线性操作。H265 SAO做的tradeoff就是首先对CTB中的pixel进行分类,再对每一个类别分别进行处理,这样避免了对每一个pixel直接进行处理带来的高码率的代价,从而转换成了对分类后的类进行的处理,而分类的类别的数目是比较少的,对于band offset和edge offset都是4个类别。因此只是需要提供4个offset值就足够。
大量模拟测试和资料显示,SAO平均可以节约2%到6%的码率,而编解码的复杂度只增加2%左右!SAO主要目的和操作原理减少源图像与重构图像之间的失真。如果只看这点,实际上每帧编码后的码率反而会增加,因为多了SAO的相关语法和语义以及补偿值的编码!其实不然,虽然当前帧的码率增加了几个字节或者几个bit,但是这点增加码字使得源图像与重构图像的失真减少,使接下来的预测残差更小了,从而大大的降低码率了!