266中帧内预测完整过程的总结_小小柴的博客-CSDN博客_帧内预测
【HEVC学习与研究】41、HEVC帧内编码的原理和实现(中)_Workshop of Wenjie.Yin-CSDN博客
c++ <<和>>的意思_ccccvvvvvcv的博客-CSDN博客_<< >>c++语言
帧内预测流程(主要参考hevc的书,可能有点过时)
主要是亮度信号的帧内预测,色度信号的过程与亮度信号差不多。
1.参考像素的获取:按照扫描的时间顺序在当前编码块左侧,左上,上方,右上及左上角的像素为参考像素。某些情况下,如参考像素在图像外,条分割外或者参考像素所属编码块不是帧内预测模式且被限制不能作为帧内预测的参考块,参考像素不可用。
根据参考像素可用不可用,分为三种情况
2.参考像素的平滑滤波:为了提高帧内的预测效率,减少噪声对预测的影响,提高预测的精度,对参考像素进行平滑滤波。平滑滤波器其实是一个3抽头的低通滤波器。
常规平滑滤波:3抽头滤波器,抽头系数[1,2,1]/4,参考像素p[x][y]滤波后对应的像素值为pF[x][y]:
左上角参考像素滤波处理(在c++中最好写成
要移的位数 <<或>> 要移的数字,如2 << 1 = 4)
>>二进制右移,<<二进制左移
pF[-1][-1] = (p[-1][0]+2xp[-1][-1]+p[0][-1]+2)>>2 (左上角像素的两倍和上方,下方像素相加 ,再加二得的二进制数字向右位移2位)
左方参考像素处理:
pF[-1][y] = (p[-1][y+1]+2xp[-1][y]+p[-1][y-1]+2)>>2 (向右位移)
如果最左下角参考像素p[-1][nTbsx2-1]没有相邻的参考像素,则滤波后的值保持不变
p[-1][nTbsx2-1] = p[-1][nTbsx2-1]
上方参考像素的滤波处理
pF[x][-1] = (p[x-1][-1]+2xp[x][-1]+p[x+1][-1]+2) >> 2
同理,如果最右上角参考像素p[nTbsx2-1][-1]没有相邻的参考像素,则滤波后的值保持不变
p[nTbsx2-1][-1] = p[nTbsx2-1][-1]
以上,开头和结尾的像素不滤波。
常规平滑滤波
强平滑滤波:只对32X32的块。有一个专门的强滤波标记strong_intra_smoothing_enabled_flag在SPS中。若标记有效,则用双线性插值滤波器进行强平滑滤波。
条件:
满足以上条件时,就需要使用强平滑滤波。(3)(4)如果成立,表明参考像素处于低纹理区域,强度为常数或接近线性变化。对这些块
,参考像素值被最末像素值和中心像素值之间的线性内插所取代(如图):
p[-1][y] = [(63-y)p[-1][-1]+(y+1)p[-1][63]+32] >> 6;
p[x][-1] = [(63-x)p[-1][-1]+(x+1)p[63][-1]+32] >> 6 (这里的63,32都是固定的数,因为强平滑滤波只有32X32的块有)
强平滑滤波
强平滑滤波通过沿用每个方向的线性内插值 取代了真实样点值,取消了小的拒不变化,这样的变化虽小,但在32X32的大杨店区域进行帧内预测时,还是会产生可见的结构性失真。
3.计算预测值
非角度类
平面(plannar)模式的预测值
平面模式适合对图像中像素值呈渐变趋势的区域进行预测。预测块内像素p的预测值由是个参考像素来决定,该像素在水平方向上的左侧参考像素b和右上方参考像素a,该像素在垂直方向上的上方参考像素d和左下角擦考像素c。b和d的值会岁位置变化而变化,但a和c的值不会变,由这是个参考像素的值加权平均得到。
predsamples[x][y] = ((nTbs - 1 - x)xp[-1][y]+(x+1)xp[nTbs][-1]+(nTbs - 1 - y)xp[x][-1]+(y+1)xp[-1][nTbs]+nTbs) >> (log2(nTbs)+1) //右移这几位
直流(DC)模式的预测值
预测值由左方和上方参考像素的适当平均而得平均值dcVal,该均值作为当前块中每个点的预测值。
对于亮度预测块,为改进边缘的过渡特性,块内紧邻参考像素的边缘像素点需要和参考像素进行加权处理。
predsamples[0][0] = (p[-1][0]+2xdcVal+p[0][-1]+2) >> 2
predsamples[x][0] = (p[x][-1]+3xdcVal+2) >> 2 x = 1,...,nTbs - 1
predsamples[0][y] = (p[-1][y]+3xdcVal+2) >> 2 y = 1,...,nTbs - 1
对于相应的色度快预测,边缘加权处理可省略
角度类
【HEVC学习与研究】41、HEVC帧内编码的原理和实现(中)_Workshop of Wenjie.Yin-CSDN博客
HM16.7学习笔记1_zzzz_新浪博客 (sina.com.cn)
H.266/VVC代码学习:帧内预测之初始化帧内预测参数(initPredIntraParams) - JavaShuo
hevc角度模式共有33种,根据表格2~10,26~34为正角度模式,11~25为负角度模式
各个模式对应的角度
又因为图像分垂直,水平两个方向,所以将2~18成为水平方向类预测模式,18~34为垂直方向类预测模式。
帧内预测值计算:
以一个垂直方向类的预测模式(18~34)为例,对某一角度模式,尺寸为nTbs预测块中的某一位置像素p[x][y]
帧内角度模式的基本原理是通过当前像素沿某个某个预测方向在参考像素集上投影,“投中”的那个参考像素就是当前像素的预测值。参考像素集是一堆参考像素的集合,如上方,左方参考像素集。。正角度方向的像素投影都可以投中到参考像素(图1),但负角度方向的像素投影可能就到负的x,y轴上了,也可能投在两个像素之间。
图1 垂直预测方向的正角度(模式31) 图2垂直预测方向的负角度(模式21)
(1)获得参考像素数组ref[x]
如果预测模式处于正角度(模式26~33和模式2~10),该数组直接拷贝预测方向上的像素值(参考像素组直接由上方或左方的像素参考集组成,只由一边的像素参考集组成)
垂直 ref[x] = p[-1+x][-1]
水平 ref[y] = p[-1][-1+y]
例:垂直预测模式时,ref[0] = p[-1][-1],ref[1] = p[0][-1]......,只由上方参考像素集组成,与左方参考像素集无关
但如果预测模式处于负角度方向,即intraPredAngle < 0,并且((nTbs x intraPredAngle) >> 5) < -1,(intraPredAngle这个变量中就保存了当前模式同水平/垂直模式映射到边界上的偏移值,就是预测模式对应的“角度”,和水平(垂直)方向偏移了多少小格子。如模式31的"角度"intraPredAngle = 17)
则参考像素序列需要进行扩充
垂直 ref[x] = p[-1][-1+((x*invAngle+128) >> 8)]
代码中也可写成ref[x] = p[-1][-1+Round[32 * x /intraPredAngle[k]]],此处的intraPredAngle[k]就是模式对应角度那个图中的A,也就是模式所对应的角度。intraPredAngle[k] = intraPredAngle
水平 ref[y] = p[-1+((y*invAngle+128) >> 8)][-1],略
这里的invAngle是反角度参数,每个模式的角度都有对应的invAngle.如下图,B就是invAngle
举个例子,块尺寸nTbs=4,角度模式为21,上方参考像素为p[x][-1],x = -1,...,2xnTbs(此处不是2xnTbs - 1,是因为下面转化为一维参考像素集时都要减去1,但x大于等于0的参考像素集须有(2xnTbs+1)个,所以不减去1,以免参考像素少一个),左方参考像素为p[-1][y],y = -1,...,2xnTbs, 一维参考像素ref[x] ,x = -nTbs, ... ,2xnTbs:
对于x>= 0时,则有:ref[x] = p[-1+x][-1],x = 0, ... ,2 x nTbs (x大于等于0时,这些参考像素集直接拷贝上方参考像素集,如图2,因为左方的参考像素集投射不到x大于等于0的参考像素上)
ref[0] = p[-1][-1],
ref[1] = p[0][-1]
......
ref[8] = p[7][-1]; 这里共9个参考像素,(2xnTbs+1)个
x < 0时 ,此时左方的参考像素集按照一定的规则投射到延伸参考像素集上,所以有
ref[x] = p[-1][-1+((x*invAngle+128) >> 8)] = p[-1][-1+Round[32 * x /intraPredAngle[k]]],x = -1, ... ,-nTbs,(左负方向轴变小),
ref[-1] = p[-1][-1+(((-1* -482)+128) >> 8)] = p[-1][-1+Round(32 * -1 /-17)] = p[-1][1],这里的预测模式为21,对应角度intraPredAngle = -17,对应的反角度参数invAngle = -482,。
接下来,ref[-1] = p[-1][3],ref[-3] = p[-1][5],ref[-4]不存在(此处显示,左方的参考像素从坐标为p[-1][1]的像素起,隔一个投射到延伸的负方向一维参考像素集上)
由此得到一维参考像素集,下面的预测可参考这个一维数组进行。
(2)参数ildx和iFact的设置
设置不同模式所对应的索引ildx和乘法因子iFact(权重参数),如式子(1)(2)所示。intraPredAngle这个变量中就保存了当前模式同水平/垂直模式映射到边界上的偏移值,就是预测模式对应的“角度”,这个“角度”不适用普通的角度单位来标识,而是和水平(垂直)方向偏移了多少小格子。如模式31的"角度"intraPredAngle = 17。
ildx表示对于垂直模式在y列和水平模式在x行的偏移值的整数部分,iFact表示偏移的小数部分 ,下面两个式子都是垂直模式(水平模式把y改成x就行,代表当前模式与水平(垂直)方向的偏移量。垂直模式用y是因为根据预测点p的竖直方向的位置,投影到参考像素行上的点的位置也不太,影响到偏移值)
ildx = ((y+1) x intraPredAngle) >> 5 式1
iFact = ((y+1) x intraPredAngle) & 31 式2
(&是按位与运算的意思,只要对应的二个二进位都为1时,结果位就为1。参与运算的两个数均以补码出现。 例如:3&10可写算式如下: 00000011&00001010 00000010 十进制2)
(3)预测值的计算
垂直 predSamples[x][y] = ((32- iFact) x ref[ x+ilddx+1 ] + iFact x ref[ x+ilddx+2 ] +16) >> 5
水平 predSamples[x][y] = ((32- iFact) x ref[ y+ilddx+1 ] + iFact x ref[ y+ilddx+2 ] +16) >> 5
predSamples[x][y] = ref[ x+ilddx+1 ]
特殊情况:如果块尺寸小于32X32,且预测模式为垂直(26),那么
predSamples[x][y] = CliplY(p[x][-1]+(([-1][y] - p[-1][-1]) >> 1)) (此处书上写的cliplY没看懂什么意思,以后更改)
(4)预测值计算原理(线性内插,原理在hevc 书P99)
对于每个预测方向,根据比例关系,可以算出预测点p[x][y]在参考像素行中的投影点位置得到投影点坐标相对于p[x][y]坐标的位移。根据水平或垂直模式,分为横坐标位移和竖坐标位移。
竖直模式下的横坐标位移 Cx / y = d / 32
水平模式下的竖坐标位移 Cy / x = d / 32 (这里的32是中心点到参考像素行的距离,具体意思还没明白,之后看代码理解)
其中Cx(Cy)表示待预测点(x,y)的横(竖)坐标和点(x,y)沿着预测方向投影待上(左)参考像素行的横(竖)坐标之差,也就是定义的偏移索引ildx;d表示预测模式方向和垂直(水平)方向的偏移距离(格数),范围为-32 ~+32,可由表查得。
所以可得(注意:这里设置为垂直预测方向26~34) 偏移索引ildx和权重因子iFact如下:
ildx = Cx = (y *d) / 32
(这个式子得出的结果与先前式1的 ildx = ((y+1) x intraPredAngle) >> 5的结果相同,可用模式31,p[-1][6]来验证,(7*17) >> 5 = (6 * 17) / 32 = 3 )
HEVC中代码是这样规定的
for (k=0;k> 5;
deltaFract = deltaPos & (32 - 1);
可明显看出deltaPos 对应((y+1) x intraPredAngle),deltaInt = ildx,deltaFract = iFact,所以这两个参数的计算最好还是用
ildx = ((y+1) x intraPredAngle) >> 5 式1
iFact = ((y+1) x intraPredAngle) & 31 式2
(4)对上一步得到的预测块的边界做边界滤波
有些预测模式在预测像素块的边界处可能产生不连续的像素值断层,对DC模式和角度预测中的水平和垂直模式尤为明显。在DC模式下,顶部和左侧边界都会产生不连续效应,因为整个预测像素值都由同一个平均值替换。对于垂直模式,左侧边界可能产生不连续边界,因为最左边一列的预测像素值复制了块上方最左侧的参考像素。对于水平模式的最顶行也存在类似的问题。
为除去沿块办结的不连续性,所以在DC模式,水平模式(10),垂直模式(26)这几种情况中,当编码PB尺寸小于32X32时,PB内边界的像素值(紧贴参考像素的那一行和一列像素)用滤波后的值取代。
另外,由于亮度分量有更为均衡的特性,预测块边界滤波操作仅限于亮度分量。
p[x][0] = p[x][0] + ((p[x][-1] - p[-1][-1]) >> 1) for x = 0...N - 1
需要根据原预测像素的位置分为三种情况: