H.266/VVC代码学习2:有关ALF

大体过程如下:
1、设置可用的过滤器形状:分两个通道,即亮度通道和色度通道;设置剪裁范围:获取片的剪裁范围;设置CTU启用标志:即确定该CTU是否进行划分。
2、首先确定CTU标志是否开启,对启用的部分重建亮度、色度系数,并且将重建YUV值存入临时YUV。得到之前的计算值。之后遍历开启了CTU标志的每个CU块,对每个块都确定其最小的宽高。
3、如果这个块对亮度滤波,则进行分类并进行对应的77滤波。对色度,如果满足条件,则继续划分,并用55的滤波器进行滤波。

具体滤波部分:
亮度有7x7,5x5两种类型的滤波器,有25个类及4种方向性,处理4x4的块;色度只有5x5类型,1个类,处理2x2的块,分类的过程在二中详细阐述。其中7x7类型需要13个系数可以滤波,5x5需要7个系数,用系数模板进行滤波的过程在三中详细阐述。

一、 重建系数(reconstructCoeff)

1、如果是对亮度分量的滤波,则存入325个系数(25类,每类13个系数)。
2、如果是对色度分量的滤波,则不需要重建系数。
3、如果采用了预测模式,每个系数=自己系数-前一排系数。

二、获取分类(deriveClassification)

亮度3232的块进行划分,亮度分量分到44的块来获取分类。
随后进行计算每个块的所有分类的值(拉普拉斯变换的第一个维度)。在各个块中获取拉普拉斯变换的值后,运算得出四种方向D的sum,计算活动性A。
对上面求到的sum进行比较:如果V>H,D=1;如果H>V,D=3;如果D0>D1,D=0;如果D1>D0,D=2。再对比水平竖直和对角线确定哪个是主方向,若差距比较大还可以附加方向强度。最终可得到块在25种分类中的所在分类及方向性,,将最终的4*4的16个块都分配上相同的分类和方向性。

三、进行滤波(filterBlk)

获取临时及重建的亮度值、stride。设置滤波区块范围,pImgYPad是竖排范围,pImg是横排范围,范围均是7。创建滤波的起始高度、终止高度、起始宽度、终止宽度,并检验是否合法。先对亮度图2与图3是滤波方法,图2是针对亮度块进行卷积得到77的滤波后的值,图3针对色度块进行卷积得到55滤波后的值。
77和55类型的滤波器,都有4种不同的方向性有不同的滤波系数顺序。处理结束当前4*4块后,得到sum值,与offset(=256)相加后,除以shift(=512)即可得到该块滤波值。

亮度的7*7滤波范围及系数模板:

									pImg6[0]			
						pImg4[-1]	pImg4[0]	pImg4[1]		
			pImg2[-2]	pImg2[-1]	pImg2[0]	pImg2[1]	pImg2[2]	
pImg0[-3]	pImg0[-2]	pImg0[-1]	pImg0[0]	pImg0[1]	pImg0[2]	pImg0[3]
			pImg1[-2]	pImg1[-1]	pImg1[0]	pImg1[1]	pImg1[2]	
						pImg3[-1]	pImg3[0]	pImg3[1]		
									pImg5[0]	



									Coeff[0]			
						Coeff[1]	Coeff[2]	Coeff[3]		
			Coeff[4]	Coeff[5]	Coeff[6]	Coeff[7]	Coeff[8]	
Coeff[9]	Coeff[10]	Coeff[11]	Coeff[12]	Coeff[11]	Coeff[10]	Coeff[9]
			Coeff[8]	Coeff[7]	Coeff[6]	Coeff[5]	Coeff[4]	
						Coeff[3]	Coeff[2]	Coeff[1]		
									Coeff[0]		

色度的5*5滤波范围及系数模板:

	              		    pImg4[0]		
                pImg2[-1]	pImg2[0]	pImg2[1]	
   pImg0[-2]	pImg0[-1]	pImg0[0]	pImg0[1]	pImg0[2]
      			pImg1[-1]	pImg1[0]	pImg1[1]
      						pImg3[0]



						Coeff[0]		
			Coeff[1]	Coeff[2]	Coeff[3]	
Coeff[4]	Coeff[5]	Coeff[6]	Coeff[5]	Coeff[4]
			Coeff[3]	Coeff[2]	Coeff[1]	
						Coeff[0]	

四、补充说明

1.亮度系数=自己系数+上一排系数,每排最后一个系数是512-2*此排和。
2.活动性A:activity = (Pel)Clip3( 0, 15, ( (sumV + sumH) * 32 ) >> 512 )。
3.分类计算:分类序号+(x+方向强度)*5
其中分类序号是0、1、2、3、4,x在D=1或3时为2,否则为0。

框架代码如下:
void AdaptiveLoopFilter::ALFProcess( CodingStructure& cs, AlfSliceParam& alfSliceParam )
{
  if( !alfSliceParam.enabledFlag[COMPONENT_Y] && !alfSliceParam.enabledFlag[COMPONENT_Cb] && !alfSliceParam.enabledFlag[COMPONENT_Cr] )
  {
    return;
  }

  // set available filter shapes
  alfSliceParam.filterShapes = m_filterShapes;

  // set clipping range
  m_clpRngs = cs.slice->getClpRngs();

  // set CTU enable flags
  for( int compIdx = 0; compIdx < MAX_NUM_COMPONENT; compIdx++ )
  {
    m_ctuEnableFlag[compIdx] = cs.picture->getAlfCtuEnableFlag( compIdx );
  }
  //============重建系数=================//
  reconstructCoeff( alfSliceParam, CHANNEL_TYPE_LUMA );
  reconstructCoeff( alfSliceParam, CHANNEL_TYPE_CHROMA );

  PelUnitBuf recYuv = cs.getRecoBuf();
  m_tempBuf.copyFrom( recYuv );
  PelUnitBuf tmpYuv = m_tempBuf.getBuf( cs.area );
  tmpYuv.extendBorderPel( MAX_ALF_FILTER_LENGTH >> 1 );

  const PreCalcValues& pcv = *cs.pcv;

  int ctuIdx = 0;
  for( int yPos = 0; yPos < pcv.lumaHeight; yPos += pcv.maxCUHeight )
  {
    for( int xPos = 0; xPos < pcv.lumaWidth; xPos += pcv.maxCUWidth )
    {
      const int width = ( xPos + pcv.maxCUWidth > pcv.lumaWidth ) ? ( pcv.lumaWidth - xPos ) : pcv.maxCUWidth;
      const int height = ( yPos + pcv.maxCUHeight > pcv.lumaHeight ) ? ( pcv.lumaHeight - yPos ) : pcv.maxCUHeight;
      const UnitArea area( cs.area.chromaFormat, Area( xPos, yPos, width, height ) );
	  //======对亮度的滤波,7*7,Y========//
      if( m_ctuEnableFlag[COMPONENT_Y][ctuIdx] )
      {
        Area blk( xPos, yPos, width, height );
        deriveClassification( m_classifier, tmpYuv.get( COMPONENT_Y ), blk );//亮度要获取分类
#if JVET_L0664_ALF_REMOVE_LUMA_5x5
        m_filter7x7Blk(m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y]);
#else
        if( alfSliceParam.lumaFilterType == ALF_FILTER_5 )
        {
          m_filter5x5Blk( m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y] );
        }
        else if( alfSliceParam.lumaFilterType == ALF_FILTER_7 )
        {
          m_filter7x7Blk( m_classifier, recYuv, tmpYuv, blk, COMPONENT_Y, m_coeffFinal, m_clpRngs.comp[COMPONENT_Y] );
        }
        else
        {
          CHECK( 0, "Wrong ALF filter type" );
        }
#endif
      }
	  //======对色度的滤波,5*5,Cb,Cr========//
      for( int compIdx = 1; compIdx < MAX_NUM_COMPONENT; compIdx++ )
      {
        ComponentID compID = ComponentID( compIdx );
        const int chromaScaleX = getComponentScaleX( compID, tmpYuv.chromaFormat );//确定色度范围(4:2:0要缩一下)
        const int chromaScaleY = getComponentScaleY( compID, tmpYuv.chromaFormat );

        if( m_ctuEnableFlag[compIdx][ctuIdx] )
        {
          Area blk( xPos >> chromaScaleX, yPos >> chromaScaleY, width >> chromaScaleX, height >> chromaScaleY );

          m_filter5x5Blk( m_classifier, recYuv, tmpYuv, blk, compID, alfSliceParam.chromaCoeff, m_clpRngs.comp[compIdx] );//5*5滤波
        }
      }
      ctuIdx++;//继续下一CTU
    }
  }
}

你可能感兴趣的:(H.266/VVC视频编码)