前面已经讲过了帧内预测的原理,但是只是讲了一下方向DC以及平面预测的概念,对其中的细节没有细讲,这里,整理http://blog.youkuaiyun.com/shaqoneal/article/details/44749057这篇博文来看看具体概念。
(1)角度预测
HEVC中的角度预测方法用于高效地对图像和视频的不同方向性结构进行建模的方法。该方法所选择的预测方向经过设计,可以达到对典型视频内容的编码效率和编码复杂度的平衡。算法对不同的预测块大小和预测方向提出了严格的低复杂度要求,因为HEVC帧内预测所支持的预测模式远远超过H.264等前期标准。在HEVC中,HEVC定义了从4×4到32×32这四种不同大小的帧内预测块尺寸,每种尺寸都支持33种不同的预测方形,所以一个解码器必须支持总共132中组合。
(1.1)角度的定义
HEVC定义了33中预测角度的集合,其精度为1/32。根据经验,图像内容中水平和垂直一致通常出现的概率超过其他方向一致。相邻方向之间的角度差越接近这两个方向便越小,越靠近对角线方向便越大,其目的在于在接近水平和垂直模式时可以提供更加精准的预测结果,而在出现机会较低的对角方向减小预测的运算负荷。各个预测方向如下图所示:
图中角度差用参数V表示,在生成参考像素时会作为获取参考数据的依据。
(1.2)参考像素对负角度方向的扩展
为了简化预测过程,编码器将当前像素块上方的参考像素p[x][-1]和左方的参考像素p[-1][y]置于一个一维数组中。对于正角度(模式26~33和模式2~10),该数组直接拷贝预测方向上的像素值,公式如下:
对于负角度,左侧和上方的参考像素都会被使用到,此时参考数组中的非负索引的元素依旧如前文所述,负索引值所表示的像素通过映射获得,公式如下:
其中B与角度参数A(V)的对应关系如下表:
这部分该如何理解呢?以下两张图分别是正向角度的垂直模式/水平模式的方向示意图:
对于不同的预测方向,预测块所使用的预测数据时不同的。由于预测像素的组织形式是一个一维数组,以顶点像素为中心向两边扩展。在正向角度预测时,只需要或正方向或负方向的预测数据级就可以为预测块进行赋值。而对于负向角度,情况将有所不同。下图表示负向角度下的预测方向示意图:
上面的这些内容呢,用我自己的语言组织一下,先看第一张正向角度、垂直类图,从右上到左下的预测方向,把这个方向放到最上面的原理图,发现这个方向代表V+2-V+32 前面又讲过,26代表垂直预测,那么与垂直预测离得近的我们称为垂直类,角度又为正,他们可以直接直接拷贝预测方向上的像素值(即上方的像素值)。
再看第三张图,从H-2到V-2,他们不仅需要上面的像素,还需要左方的像素值。
那么在HM中,我们知道xPredIntraAng来决定预测方向,因此找到这个函数。
后面原博的分析是HM10,和16.3不一样,我就按我的方法分析一下吧:
首先在
Void TComPrediction::predIntraAng( const ComponentID compID, UInt uiDirMode, Pel* piOrg /* Will be null for decoding */, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, Bool bAbove, Bool bLeft, const Bool bUseFilteredPredSamples, const Bool bUseLosslessDPCM )
{
const ChromaFormat format = rTu.GetChromaFormat();
const ChannelType channelType = toChannelType(compID);
const TComRectangle &rect = rTu.getRect(isLuma(compID) ? COMPONENT_Y : COMPONENT_Cb);
const Int iWidth = rect.width;
const Int iHeight = rect.height;
assert( g_aucConvertToBit[ iWidth ] >= 0 ); // 4x 4
assert( g_aucConvertToBit[ iWidth ] <= 5 ); // 128x128
//assert( iWidth == iHeight );
Pel *pDst = piPred;
// get starting pixel in block
const Int sw = (2 * iWidth + 1);
if ( bUseLosslessDPCM )
{
const Pel *ptrSrc = getPredictorPtr( compID, false ); //获取参考数据的指针 ,指向的是当前块的参考数据
// Sample Adaptive intra-Prediction (SAP)
if (uiDirMode==HOR_IDX)
{
// left column filled with reference samples 用左列的参考样值填充 水平方向
// remaining columns filled with piOrg data (if available).
for(Int y=0; y<iHeight; y++)
{
piPred[y*uiStride+0] = ptrSrc[(y+1)*sw];
}
if (piOrg!=0)
{
piPred+=1; // miss off first column
for(Int y=0; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride)