HEVC函数入门(7)——帧内预测-详细概念和HM16.3实现(下)

来源:互联网 发布:js当前时间减一小时 编辑:程序博客网 时间:2024/06/18 08:01

首先说明本文引自:http://blog.csdn.net/shaqoneal/article/details/44759561
这里我看的就没有上一篇那么懂了,所以很多地方都只是单纯的复制,另外也有一些个人的理解
(1)亮度帧内预测模式的预测
HEVC对每种PU大小共支持总计33种角度模式,外加上DC和平面模式。由于支持的模式更多,类似于H.264的单一最可能模式在HEVC中效率不高。HEVC针对每种PU大小定义了三个最可能模式,其选择依赖于相邻PU所选的模式。同时,由于最可能模式之外的模式概率分布接近平均,这样也可以由一个不经过CABAC的定长编码表示的结构来从剩余32个模式中指定一个模式。
最可能模式的选择根据左侧和上方的相邻块的模式确定。如果某一个相邻块不是帧内编码或者编码模式为PCM模式,或左边PU处于当前CTU之外,那么该块的模式在这个过程中等同于DC模式。设左侧和上方PU的模式分别为A和B,如果A≠B,那么这两个模式分别设为MPM[0]和MPM[1]。对于MPM[2]的确定需要遵循以下原则:①如果A或B都不是平面模式,那么MPM[2]设为平面模式;②否则,若A或B都不是DC模式,那么MPM[2]设为DC模式;③否则(即AB中有一个平面一个DC模式),MPM[2]设为模式26,即垂直模式。如果A=B,那么确定MPM的方法如下:①如果A和B都不是角度预测模式,那么MPM分别设定为平面、DC和垂直模式;②否则,MPM[0]设为A/B,MPM[1]和MPM[2]选择A的相邻模式,公式如下:
这里写图片描述
三个最可能模式确定后,会按照模式序号进行排序。如果当前预测模式等同于三个最可能模式之一,那么只有该模式在MPM的索引值会传递给解码器,否则将会传递一个5位且不经过CABAC的语法元素表示在MPM之外所选择的帧内预测模式。
该部分的实现如下(这里我先按照自己的想法找这段代码,我认为应该在estIntraPredLumaQT,因为是讲亮度预测的,但是看原文不对O(∩_∩)O哈哈~,不过不要紧,我也建议大家思考一下当前说的代码可能在哪里,有助于理解结构,现在没找到,切到雷神的那个图中去,没找到,所以我切换到TEncCU.cpp找到了TComDataCU这个类,然后在类里搜索getIntraDirLumaPredictor,没找到,想到前面博客中,原博中带Luma的,HM16.3常常不带,于是搜索getIntraDirPredictor成功找到!):

/** Get most probable intra modes*\param   uiAbsPartIdx    partition index*\param   uiIntraDirPred  pointer to the array for MPM storage*\param   compID          colour component ID*\param   piMode          it is set with MPM mode in case both MPM are equal. It is used to restrict RD search at encode side.*\returns Number of MPM*/Void TComDataCU::getIntraDirPredictor( UInt uiAbsPartIdx, Int uiIntraDirPred[NUM_MOST_PROBABLE_MODES], const ComponentID compID, Int* piMode  ){  TComDataCU* pcCULeft, *pcCUAbove;  UInt        LeftPartIdx  = MAX_UINT;  UInt        AbovePartIdx = MAX_UINT;  Int         iLeftIntraDir, iAboveIntraDir;  const ChannelType chType = toChannelType(compID);  const ChromaFormat chForm = getPic()->getChromaFormat();  // Get intra direction of left PU  pcCULeft = getPULeft( LeftPartIdx, m_absZIdxInCtu + uiAbsPartIdx );//获取左方PU    if (isChroma(compID))  {    LeftPartIdx = getChromasCorrespondingPULumaIdx(LeftPartIdx, chForm);  }  iLeftIntraDir  = pcCULeft ? ( pcCULeft->isIntra( LeftPartIdx ) ? pcCULeft->getIntraDir( chType, LeftPartIdx ) : DC_IDX ) : DC_IDX;//左方PU为空或非Intra,左方的PU模式则设置为DC,否则设置为左方PU的模式  // Get intra direction of above PU  pcCUAbove = getPUAbove( AbovePartIdx, m_absZIdxInCtu + uiAbsPartIdx, true, true );//获取上方PU   if (isChroma(compID))  {    AbovePartIdx = getChromasCorrespondingPULumaIdx(AbovePartIdx, chForm);  }  iAboveIntraDir = pcCUAbove ? ( pcCUAbove->isIntra( AbovePartIdx ) ? pcCUAbove->getIntraDir( chType, AbovePartIdx ) : DC_IDX ) : DC_IDX;//上方PU为空或非Intra,上方的PU模式则设置为DC,否则设置为上方PU的模式   if (isChroma(chType))  {    if (iLeftIntraDir  == DM_CHROMA_IDX)    {      iLeftIntraDir  = pcCULeft-> getIntraDir( CHANNEL_TYPE_LUMA, LeftPartIdx  );    }    if (iAboveIntraDir == DM_CHROMA_IDX)    {      iAboveIntraDir = pcCUAbove->getIntraDir( CHANNEL_TYPE_LUMA, AbovePartIdx );    }  }  assert (2<NUM_MOST_PROBABLE_MODES);  if(iLeftIntraDir == iAboveIntraDir)  { //模式A和模式B相等的情况      if( piMode )    {      *piMode = 1;    }    if (iLeftIntraDir > 1) // angular modes    {//如果二者都是角度预测,那么MPM[0]设置为该角度模式,MPM[1]和MPM[2]设置为该模式的相邻模式       uiIntraDirPred[0] = iLeftIntraDir;      uiIntraDirPred[1] = ((iLeftIntraDir + 29) % 32) + 2;      uiIntraDirPred[2] = ((iLeftIntraDir - 1 ) % 32) + 2;    }    else //non-angular    {//如果二者都不是角度预测,那么三种模式分别设置为平面、DC和垂直模式      uiIntraDirPred[0] = PLANAR_IDX;      uiIntraDirPred[1] = DC_IDX;      uiIntraDirPred[2] = VER_IDX;    }  }  else  {//模式A与模式B不等     if( piMode )    {      *piMode = 2;    }    uiIntraDirPred[0] = iLeftIntraDir;//MPM[0]和MPM[1]分别设置为这两种模式    uiIntraDirPred[1] = iAboveIntraDir;    if (iLeftIntraDir && iAboveIntraDir ) //both modes are non-planar    { //当两个模式都不是平面模式时,MPM[2]设置为平面模式      uiIntraDirPred[2] = PLANAR_IDX;    }    else    { //至少有一个是平面模式时,如果另一个是DC模式,那么MPM[2]设置为垂直模式;如果另一个不是DC模式,那么MPM[2]设置为DC模式        uiIntraDirPred[2] =  (iLeftIntraDir+iAboveIntraDir)<2? VER_IDX : DC_IDX;    }  }  for (UInt i=0; i<NUM_MOST_PROBABLE_MODES; i++)  {    assert(uiIntraDirPred[i] < 35);  }}

(2)色度帧内预测模式的导出
为了在增加了预测模式的数量的同时降低传输负载,HEVC定义了INTER_DERIVED模式表示该色度PU使用亮度PU相同的预测模式。对于一个PU,只有平面、垂直、水平、DC和导出模式可供选择。如果一个色度PU选择了导出模式,那么帧内预测编码按照对应的亮度PU的模式进行。角度预测模式34用于在推导模式为前四种模式时做替换之用,替换原则如下表:
这里写图片描述
(3)帧内预测模式编码的语法结构
经过排序的三个最可能模式分别为SMPM[0]、SMPM[1]和SMPM[2]。prev_intra_luma_pred_flag表示亮度帧内预测模式等于三者之一,若相等,则定义mpm_idx表示SMPM[mpm_idx]为选定的帧内预测模式;否则,定义语法元素rem_intra_luma_pred_mode直接指定选定的帧内预测模式取值为[0,31]。亮度模式导出方法如下:①设L=rem_intra_luma_pred_mode;②对于i=0,1,2,若L≥SMPM[i],则L++。
对于亮度帧内预测模式,导出模式出现的概率最高,其余四种的概率基本一致。语法元素intra_chroma_pred_mode二值化的方法如下表:
这里写图片描述
只想说这部分真的看不懂,先放着,等以后理解别的地方能把这里理解了再回来写一下自己的理解。
5、编码算法
由于HEVC定义的模式数量较多,在大多数场合下对所有模式进行率失真计算是不现实的。在HEVC参考代码中,SATD用于在进行率失真优化前筛选候选的亮度帧内预测模式。进入Full RDO的预测模式的数量根据对应PU的大小确定:4×4和8×8时8个,其他尺寸时3个。对于这些模式以及MPM中的候选模式,进行预测和变换操作获取所需编码数据量和对应失真。最后率失真最低的模式被选中。对于色度帧内编码,由于模式数量较少,所有可能的预测模式都会基于率失真代价进行评估。
学术界对HEVC提出了多种快速帧内预测的算法。其中之一就是减少块尺寸的种类,如根据空间相邻块之前的判决的快速CU尺寸和模式判定算法、根据贝叶斯判决准则的CU筛选算法。另一种是减少候选帧内模式的方法,如在率失真计算阶段减少候选模式数量并强制使用最可能模式的方法、根据源图像方向性和相邻块进行模式预筛选的方法等。

6、HEVC与H.264帧内编码的主要区别
HEVC和H.264帧内编码都是基于空间图像预测的方法,预测后都会进行变换编码,而HEVC的算法更加复杂。
第一,为了同HEVC的块分割结构一致,并且更适合于平滑图像区域的编码,HEVC支持的预测块大小最大可到32×32;
第二,预测的方向从H.264的8种增加到了33种用于提升对方向性结构的预测效果。HEVC可选的所有预测方向适用于亮度和色度,而H.264适用于色度的方向只有水平和垂直两种。并且HEVC针对垂直、水平和DC模式在边界像素上进行了优化;
第三,HEVC在参考数据部分缺失的情况下可以对其进行补全,并在这种情况下可以使用所有预定的预测模式;
第四,预测模式编码次用了同H.264不同的方法,使用三个最可能模式进行预测,且选中的模式始终作为色度分量的有效候选模式之一;
以上区别总结如下表:
这里写图片描述

阅读全文
0 0