根据h264标准,16x16块plane模式的预测过程如下所示:
上述公式标准中没有解释原理,网上也找不到相关资料。所以自己花了点时间分析了它,记录一下结果。
仔细观察上面式子可以看到,H和V 代表了水平方向和垂直方向的梯度,b,c是H,V的缩放,其中+32是为了做到四舍五入。a代表了右上像素和坐下像素的均值。
对这些值进行缩放和移位操作,是为了避免除法,下面会有更详细的说明。
宏块最中间的像素P(7,7)的预测值是右上像素和坐下像素的均值,其他像素根据到中间点的距离和两个方向的梯度算出。
这种算法可以根据左邻像素和右邻像素的值和趋势,预测整个宏块的值。下面是一个例子。最上面一行和最坐标一行是参考像素,其他是预测值。
[[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
[ 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18]
[ 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
[ 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
[ 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21]
[ 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22]
[ 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]
[ 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24]
[ 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25]
[10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26]
[11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27]
[12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28]
[13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29]
[14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30]
[15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31]
[16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32]]
图像如下:
下面分析h264中平面模式预测公式的由来。
首先为了简化问题,假设左邻像素都为0,上邻近像素为
P[x, -1]= x+1 , x = [-1:15]
期望得到的预测值如下:
[[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16]]
根据式子 8-122 此时H=408
设M 为右上像素和左下像素的均值,M= (p[15,-1]+p[-1,15])/2 = 8
则预测值应为
P[x,y] = M + α * p[x-7]
其中α代表水平方向的梯度,也即α = dP[x,y]/dx = 1
此时 α=H/408
这个式子可以推广到H值为其他的情况。
所以预测公式为:
P[x,y] = M + H/408 * p[x-7]
可以根据这个公式进行plane模式的预测。但是这个公式存在一个除法,在计算机中,除法指令的执行时间通常是加法或者乘法的几十倍。所以对上述公式做一下改造:
其中32M 即为公式8-119 中的a
分子右半部分即为公式8-120种的b
分母32即为公式8-118种右移5位的操作。
将竖直方向的梯度也考虑进来,就是h264种的平面预测方法。
这个算法的关键是用2^11 = 2024替代5*408=2040,避免了除法。
分析这么多,先现在可以小试一下牛刀,假设I8x8有plane模式(当然h264没有),推导一下I8x8的平面预测公式。
编辑公式太耗时,直接看代码吧。
def predict8_p(pred,x0, y0,src):
H = np.long(0)
V = np.long(0)
for i in range(4):
H += (i + 1) * (int(src[y0 - 1, x0 + 4 + i]) - int(src[ y0 - 1,x0 + 2 - i]));
V += (i + 1) * (int(src[y0 + (4 + i), x0 - 1]) - int(src[ y0 + (2 - i),x0-1]));
#print(H)
a = 32 * (int(src[y0 + 7,x0 - 1, ]) + int(src[ y0 - 1,x0 + 7,]));
b = np.floor((17 * H + 8) / 16);
c = np.floor((17 * V + 8) / 16 );
i00 = a - b * 3 - c * 3 + 32;
for y in range(8):
pix = i00;
for x in range(8):
pred[y0+y,x0+x] = clip_pixel(np.floor(pix/64));
pix += b;
i00 += c;
这个算法中,同样用近似替代的方法,避免了除法。
算法效果如下:
最左,最上一行是参考像素,其他为预测值。
另一个例子:
欢迎留言交流指正。