【VTM10.0】帧内之PDPC技术

PDPC (Position dependent intra prediction combination)

一种对预测值的修正的技术。部分帧内模式在进行帧内预测之后,进行PDPC的加权平均计算,得到最终预测值。

分为以下三种情况处理:

  • Planar/DC
  • Hor/Ver
  • 角度模式 2~17 和 51~66

在IntraPrediction.cpp中的initPredIntraParams函数中,说明了使用PDPC的条件

m_ipaParam.applyPDPC    = (puSize.width >= MIN_TB_SIZEY && puSize.height >= MIN_TB_SIZEY) && m_ipaParam.multiRefIndex == 0;
//要满足长和宽都大于等于4并且使用的第0个参考行

if (intraPredAngleMode < 0)
{//模式19到49不使用PDPC
  m_ipaParam.applyPDPC = false;
}
else if (intraPredAngleMode > 0)
{其他的角度(18水平和50垂直除外)要angularScale>=0才能使用PDPC。angularScale这个我还没搞明白。
  const int sideSize = m_ipaParam.isModeVer ? puSize.height : puSize.width;
  const int maxScale = 2;

  m_ipaParam.angularScale = std::min(maxScale, floorLog2(sideSize) - (floorLog2(3 * m_ipaParam.absInvAngle - 2) - 8));
  m_ipaParam.applyPDPC &= m_ipaParam.angularScale >= 0;
}

intraPredAngleMode与角度模式的对应关系
(所以有可能angularScale>=0表示的是非宽角度的模式,让宽角度的模式不使用PDPC)
在这里插入图片描述

贴一个其余地方看到的使用条件:在这里插入图片描述
PDPC技术代码(VTM10.0):
关于DC模式与PLANAR模式的代码在IntraPrediction.cpp中的predIntraAng函数。

关于VER模式,HOR模式以及角度模式的代码在IntraPrediction.cpp中的xpredIntraAng函数。

1.Planar/DC
用上边像素和左边像素一起来加权。
图中公式表示权值:
上边像素加权权值和y坐标相关;
左边像素加权权值和x坐标相关;
左上角的像素不进行加权
在这里插入图片描述
PDPC代码
PLAMNAR与DC模式:

if (m_ipaParam.applyPDPC)
  {
    PelBuf dstBuf = piPred;
    const int scale = ((floorLog2(iWidth) - 2 + floorLog2(iHeight) - 2 + 2) >> 2);
    CHECK(scale < 0 || scale > 31, "PDPC: scale < 0 || scale > 31");

    if (uiDirMode == PLANAR_IDX || uiDirMode == DC_IDX)
    {
      for (int y = 0; y < iHeight; y++)
      {
        const int wT   = 32 >> std::min(31, ((y << 1) >> scale));//得到上侧点的加权值
        const Pel left = srcBuf.at(y + 1, 1);//得到左侧像素点
        for (int x = 0; x < iWidth; x++)
        {
          const int wL    = 32 >> std::min(31, ((x << 1) >> scale));//得到左侧的加权值
          const Pel top   = srcBuf.at(x + 1, 0);//得到对应的上方像素点
          const Pel val   = dstBuf.at(x, y);//得到当前像素点
          dstBuf.at(x, y) = val + ((wL * (left - val) + wT * (top - val) + 32) >> 6);//使用左侧和上方像素点进行加权
        }
      }
    }
  }

2.Hor/Ver
对于水平模式18,使用上侧和左上角像素修正
(个人认为这里WTL[x][y]=-WT[y],原因可具体看下面代码的注释)

在这里插入图片描述
对于垂直模式50,使用左侧像素和左上角像素修正在这里插入图片描述
PDPC代码
VER与HOR模式:
这里只有VER的代码,因为在角度模式时,若参考的是左边的像素,那么会延对角线进行翻转,转换为参考上边。因此预测使用上方像素,而加权使用的左侧像素。

if (m_ipaParam.applyPDPC)
      {
        const int scale   = (floorLog2(width) + floorLog2(height) - 2) >> 2;
        const Pel topLeft = refMain[0];//得到左上方的像素点
        const Pel left    = refSide[1 + y];//得到左侧的像素点
        for (int x = 0; x < std::min(3 << scale, width); x++)
        {
          const int wL  = 32 >> (2 * x >> scale);
          const Pel val = pDsty[x];
          pDsty[x]      = ClipPel(val + ((wL * (left - topLeft) + 32) >> 6), clpRng);
 //进行加权,注意这里减的是topLeft,左上方的像素点
        }
      }

3.角度模式 2~17 和 51~66

只需要延长线上的点进行加权
在这里插入图片描述

在这里插入图片描述
PDPC代码
角度模式:

if (m_ipaParam.applyPDPC)
      {
        const int scale       = m_ipaParam.angularScale;
        int       invAngleSum = 256;

        for (int x = 0; x < std::min(3 << scale, width); x++)
        {
          invAngleSum += absInvAngle;

          int wL   = 32 >> (2 * x >> scale);
          Pel left = refSide[y + (invAngleSum >> 9) + 1];
          pDsty[x] = pDsty[x] + ((wL * (left - pDsty[x]) + 32) >> 6);
        }
      }

猜你喜欢

转载自blog.csdn.net/zzy_pphz/article/details/116501283