【HEVC学习与研究】35、帧内预测参考数据的获取和滤波处理

简介: 帧内预测的参考像素值的获取在标准文档的8.4.4.2.2中指明。 举例说明,当前demo中,我们用来单步调试的第一个CU为64×64像素大小,那么参考像素由两部分组成,一部分包含2×64+1=129个,另一部分包含2×64=128个像素。

帧内预测的参考像素值的获取在标准文档的8.4.4.2.2中指明。

举例说明,当前demo中,我们用来单步调试的第一个CU为64×64像素大小,那么参考像素由两部分组成,一部分包含2×64+1=129个,另一部分包含2×64=128个像素。这两部分分别作为垂直和水平方向上的预测数据。在编码的过程中,根据预测数据是否可得,共分为两种情况:

第一种:所有的预测数据都不可得。最直观的情况就是一帧数据中的第一个CU,该CU左侧和上方的数据都不存在,如下图所示。此时所有的预测数据都会制定一个默认值,计算方法为:1 << (bitDepth - 1);(图中的格子数只是示意图,不代表CU的像素大小和参考像素的个数)。


第二种:至少有一个像素点是可获得的,如下图所示。如果参考数据中的第一个点是不可获得的,那么将沿着当前CU的边缘,先从下到上,后从左到右查找第一个可获得的参考点并赋给第一个点;对于其他的点,如果不可得,那么就直接复制它前面一个参考点的值。如果所有点都是可获得的,那么参考数据直接使用该值就可以了。


基本算法已经明了,接下来研究一下HM中的实现。代码如下:

Void TComPattern::fillReferenceSamples(Int bitDepth, Pel* piRoiOrigin, Int* piAdiTemp, Bool* bNeighborFlags, Int iNumIntraNeighbor, Int iUnitSize, Int iNumUnitsInCu, Int iTotalUnits, UInt uiCuWidth, UInt uiCuHeight, UInt uiWidth, UInt uiHeight, Int iPicStride, Bool bLMmode )
{
  Pel* piRoiTemp;
  Int  i, j;
  Int  iDCValue = 1 << (bitDepth - 1);

  if (iNumIntraNeighbor == 0)//所欲参考点均不可得,按照DC模式设置参考点
  {
    // Fill border with DC value
    for (i=0; i<uiWidth; i++)
    {
      piAdiTemp[i] = iDCValue;//<span style="font-family: Arial, Helvetica, sans-serif;">piAdiTemp指向数据接收内存,保存了实际的参考像素数组的地址;</span>
    }
    for (i=1; i<uiHeight; i++)
    {
      piAdiTemp[i*uiWidth] = iDCValue;
    }
  }
  else if (iNumIntraNeighbor == iTotalUnits)//所有参考点都可获得,直接设为当前CU的参考值
  {
    // Fill top-left border with rec. samples
    piRoiTemp = piRoiOrigin - iPicStride - 1;//左上角边界,其实就是CU左上角的一个点
    piAdiTemp[0] = piRoiTemp[0];

    // Fill left border with rec. samples
    piRoiTemp = piRoiOrigin - 1;//当前CU左上顶点的左边像素

    if (bLMmode)
    {
      piRoiTemp --; // move to the second left column
    }

    for (i=0; i<uiCuHeight; i++)//将左列的像素设为参考像素
    {
      piAdiTemp[(1+i)*uiWidth] = piRoiTemp[0];
      piRoiTemp += iPicStride;
    }

    // Fill below left border with rec. samples
    for (i=0; i<uiCuHeight; i++)//继续将该列下面的像素值作为左下方的参考像素
    {
      piAdiTemp[(1+uiCuHeight+i)*uiWidth] = piRoiTemp[0];
      piRoiTemp += iPicStride;
    }

    // Fill top border with rec. samples
    piRoiTemp = piRoiOrigin - iPicStride;//指向当前CU左上角像素的正上方
    for (i=0; i<uiCuWidth; i++)
    {
      piAdiTemp[1+i] = piRoiTemp[i];
    }
    
    // Fill top right border with rec. samples
    piRoiTemp = piRoiOrigin - iPicStride + uiCuWidth;//当前CU右上方的像素起始位置
    for (i=0; i<uiCuWidth; i++)
    {
      piAdiTemp[1+uiCuWidth+i] = piRoiTemp[i];
    }
  }
  else // reference samples are partially available
  {
    Int  iNumUnits2 = iNumUnitsInCu<<1;
    Int  iTotalSamples = iTotalUnits*iUnitSize;
    Pel  piAdiLine[5 * MAX_CU_SIZE];
    Pel  *piAdiLineTemp; 
    Bool *pbNeighborFlags;
    Int  iNext, iCurr;
    Pel  piRef = 0;

    // Initialize
    for (i=0; i<iTotalSamples; i++)//用均值模式进行初始化
    {
      piAdiLine[i] = iDCValue;
    }
    
    // Fill top-left sample
    piRoiTemp = piRoiOrigin - iPicStride - 1;//指向重建像素中当前CU的左上角位置
    piAdiLineTemp = piAdiLine + (iNumUnits2*iUnitSize);
    pbNeighborFlags = bNeighborFlags + iNumUnits2;
    if (*pbNeighborFlags)//如果左上方的参考数据可用
    {
      piAdiLineTemp[0] = piRoiTemp[0];
      for (i=1; i<iUnitSize; i++)
      {
        piAdiLineTemp[i] = piAdiLineTemp[0];
      }
    }

    // Fill left & below-left samples
    piRoiTemp += iPicStride;//从左上顶点的左上角移动到左方
    if (bLMmode)
    {
      piRoiTemp --; // move the second left column
    }
    piAdiLineTemp--;//缓存指针前移一位
    pbNeighborFlags--;//可用性标记指针前移一位
    for (j=0; j<iNumUnits2; j++)
    {
      if (*pbNeighborFlags)
      {
        for (i=0; i<iUnitSize; i++)//判断过程分组进行处理,如对于一个32×32的CU,左侧和左下侧共64个预测点,总共进行16×4次赋值
        {
          piAdiLineTemp[-i] = piRoiTemp[i*iPicStride];
        }
      }
      piRoiTemp += iUnitSize*iPicStride;
      piAdiLineTemp -= iUnitSize;
      pbNeighborFlags--;
    }

    // Fill above & above-right samples
    piRoiTemp = piRoiOrigin - iPicStride;//水平方向上的处理与垂直方向类似
    piAdiLineTemp = piAdiLine + ((iNumUnits2+1)*iUnitSize);
    pbNeighborFlags = bNeighborFlags + iNumUnits2 + 1;
    for (j=0; j<iNumUnits2; j++)
    {
      if (*pbNeighborFlags)
      {
        for (i=0; i<iUnitSize; i++)
        {
          piAdiLineTemp[i] = piRoiTemp[i];
        }
      }
      piRoiTemp += iUnitSize;
      piAdiLineTemp += iUnitSize;
      pbNeighborFlags++;
    }

    // Pad reference samples when necessary
    iCurr = 0;
    iNext = 1;
    piAdiLineTemp = piAdiLine;//指向参考数组的起点,见上图
    while (iCurr < iTotalUnits)//遍历给定的参考点
    {
      if (!bNeighborFlags[iCurr])//某个点不可获得
      {
        if(iCurr == 0)//第一个参考点就找不到
        {
          while (iNext < iTotalUnits && !bNeighborFlags[iNext])//找到第一个可以获得的点
          {
            iNext++;
          }
          piRef = piAdiLine[iNext*iUnitSize];//记录该点的值
          // Pad unavailable samples with new value
          while (iCurr < iNext)//将找到的可用参考点赋给第一个参考点(以4个像素点一组为单位)
          {
            for (i=0; i<iUnitSize; i++)
            {
              piAdiLineTemp[i] = piRef;
            }
            piAdiLineTemp += iUnitSize;
            iCurr++;
          }
        }
        else
        {
          piRef = piAdiLine[iCurr*iUnitSize-1];//不可用的点不是第一个参考点,查找前一个可用的点为其赋值。
          for (i=0; i<iUnitSize; i++)
          {
            piAdiLineTemp[i] = piRef;
          }
          piAdiLineTemp += iUnitSize;
          iCurr++;
        }
      }
      else//当前点可用,pass
      {
        piAdiLineTemp += iUnitSize;
        iCurr++;
      }
    }

    // Copy processed samples 输出前面所准备的数据
    piAdiLineTemp = piAdiLine + uiHeight + iUnitSize - 2;
    for (i=0; i<uiWidth; i++)
    {
      piAdiTemp[i] = piAdiLineTemp[i];
    }
    piAdiLineTemp = piAdiLine + uiHeight - 1;
    for (i=1; i<uiHeight; i++)
    {
      piAdiTemp[i*uiWidth] = piAdiLineTemp[-i];
    }
  }
}


目录
相关文章
|
9月前
|
机器学习/深度学习 算法
m基于OFDM+QPSK和DNN深度学习信道估计的无线图像传输matlab仿真,输出误码率曲线,并用实际图片进行测试
m基于OFDM+QPSK和DNN深度学习信道估计的无线图像传输matlab仿真,输出误码率曲线,并用实际图片进行测试
295 0
|
11月前
|
机器学习/深度学习 编解码 人工智能
VDSR、DRRN、LapSRN、RCAN、DSRN…你都掌握了吗?一文总结超分辨率分析必备经典模型(二)(2)
VDSR、DRRN、LapSRN、RCAN、DSRN…你都掌握了吗?一文总结超分辨率分析必备经典模型(二)
170 0
|
11月前
|
机器学习/深度学习 编解码 监控
VDSR、DRRN、LapSRN、RCAN、DSRN…你都掌握了吗?一文总结超分辨率分析必备经典模型(二)(1)
VDSR、DRRN、LapSRN、RCAN、DSRN…你都掌握了吗?一文总结超分辨率分析必备经典模型(二)
230 0
|
机器学习/深度学习
ECCV 2022|DynamicDepth:动态场景下的多帧自监督深度估计
在DOMD进行crop-粘贴的操作之后,图片中已不存在动态物体,但是新的问题又出现了,那就是遮挡区域,如下图的输入部分,我们可以看到crop后的部分区域是黑色的,因为该部分实际被遮挡了,因此本文在构建cost volume的时候需要考虑到被遮挡的情况。如上图所示,被遮挡部分的特征被临近部分的数据所填充,这样可以促进训练的梯度流向附近的non-occluded区域。
158 0
|
机器学习/深度学习 人工智能 自然语言处理
一文尽览 | 首篇Transformer在3D点云中的应用综述(检测/跟踪/分割/降噪/补全)(下)
Transformer 一直是自然语言处理 (NLP) 和计算机视觉 (CV) 的核心。NLP 和 CV 的巨大成功激发了研究者对 Transformer 在点云处理中的使用的探索。但是,Transformer如何应对点云的不规则性和无序性?
一文尽览 | 首篇Transformer在3D点云中的应用综述(检测/跟踪/分割/降噪/补全)(下)
|
机器学习/深度学习 算法 Python
机器学习中的音频特征:理解Mel频谱图
机器学习中的音频特征:理解Mel频谱图
518 0
机器学习中的音频特征:理解Mel频谱图
|
机器学习/深度学习 算法 计算机视觉
【语音去噪】基于小波硬阈值语音去噪含Matlab源码
【语音去噪】基于小波硬阈值语音去噪含Matlab源码
【语音去噪】基于小波硬阈值语音去噪含Matlab源码
|
算法
《数字视频和高清:算法和接口》一1.3图像采样
本节书摘来华章计算机《数字视频和高清:算法和接口》一书中的第1章 ,第1.3节, [加]查尔斯·波因顿(Charles Poynton)著 刘开华 褚晶辉 马永涛 吕卫 宫霄霖 等译 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。
750 0

热门文章

最新文章