H.264压缩技术之帧间预测(P Frame)——Matlab源码解析

前言

今天翻看日历,发现距离上一次的I帧编码的博客已经搁了一个月了…,今天把这个坑填上。
另外注意:这里的子目录,代表进入了函数中。例如:3.main(),那么3.1就是main{ code }

前文回顾:强烈建议回顾一下Overview部分。
H.264压缩技术之总览(Overview)——Matlab源码解析.
H.264压缩技术之视频基础(foundation of learning video)——Matlab源码解析.
H.264压缩技术之帧内预测(I Frame)——Matlab源码解析.

1.环境初始化

这里主要是做了四件事:

  • 拿出参考帧(第一帧是I帧,所以一定是存在参考帧的)
  • 设置初始分块大小 bs
  • 设置运动向量的搜索范围 mr
  • 创建运动向量容器 mvm
    在这里插入图片描述
Seq(:,:,2)=double(VideoSeq_input(:,:,k))  %%k代表是第几帧
X(:,:,2)=Seq(:,:,2);%%注意X(:,:,1)中保留的就是参考帧!!!I帧编码部分已经保存过了
[Seq_r(:,:,2),bits] = encode_p_frame(X,Quant(q),ext,block_size);
%%开始对这一帧进行P帧编码,其实X中包含了要编码的帧和前一个参考帧
%%ext不用管就是一个标志
%Quant代表量化因子
%%当然在前面已经gobal了全局变量 mvm mr bs

2.开始模式决定

进入encode_p_frame函数——>开始模式决定(mode_decision)

mode_decision(bs,mr,i,j);
%%这里出现了i,j就代表已经进行分块处理了

从我们需要操作的帧中,按bs大小开始取块,并进行如下四种预测。

注: 每个块都得经理如下四种模式,但是这里只介绍第一种完全预测,其他的都是类似的,由读者自行探索。
在这里插入图片描述上述四种模式在源码中的函数分别为:

  • motion_comp_full
  • motion_comp_vert
  • motion_comp_horz
  • motion_comp_quad

2.1进行完全预测(motion_comp_full)

我们从mode_decision函数进入后,里面进入完全预测模式。
你可以看到输入的变量和上面的模式决定所输入的变量是一样的。
在这里插入图片描述

2.1.1 进行块运动补偿

这里调用了一个窗函数swr,需要我们知道的是,这个swr操作之后生成的变量中,包含了参考帧的像素信息(可以理解为卷积操作,但不是卷积)。
并且获取需要操作的块的位置curr.
在这里插入图片描述

2.1.1.1 完全模式的运动向量预测find_median_mv_pred(bs,i,j,mvm)

多说一嘴:程序如何判断这个块是完全模式,还是对角模式呢?
其实我们前面有一个标记,来表示这个块当前的模式:

switch mvp_mode
    case 'm'  %%这里的m就代表的是我要进行完全模式的向量预测
        [mvxp,mvyp] = find_median_mv_pred(i,j,bsx);
    case 'a'
        [mvxp,mvyp] = find_mv_pred_a(i,j,bsx);
    case 'b'
        [mvxp,mvyp] = find_mv_pred_b(i,j,bsx);
    case 'c'
        [mvxp,mvyp] = find_mv_pred_c(i,j,bsx);
end

好我们进入find_median_mv_pred.
初始化的mvm容器中因为没有运动向量,所以里面一开始全部都是inf.
这个函数的核心就是计算出mvp 用来更新mvm和后续的运动向量mvpx,mvpy的计算。
在这里插入图片描述

mvxp = mvp(1);
%%简单粗暴的将算出来的mvp赋值给mvxp,代表这个块的完全模式下的x方向的运动向量为mvxp
mvyp = mvp(2);
2.1.1.2 进行运动补偿

注:区别于2.1.1的块运动补偿,这里是具体的运动补偿的操作部分。上面只是这个主函数名字。
这一步的工作其实还挺多的,我们一步一步的来细细分析:

  • 通过函数fun,来实现了对搜索窗口的扩充(镜像填充),暂时理解为扩充即可。
  • 计算编码mvp所需的比特数mvr,如何计算呢?通过比较Mvp值得大小。比如下图的两个箭头,可以看到左边的箭头要比右边的长,那么左边所需的比特数就比右边的多。
  • 计算当前块和候选块的绝对误差sad。这里解释一下fun2函数,这相当于是预测出的一个块,通过swr。然后与真实的块curr进行一个减法,算出残差。
  • 计算失真代价J,J值得大小就用来评判这个预测适不适合这种模式。我没有了两个值,一个mvr,sad,这两个值就来评判,我们这个预测到底好不好,把他丢进fun3函数计算即可。(fun3函数具体参见代码,就是一个带拉格朗日乘子加成操作)
    在这里插入图片描述

既然我们确定了要找到J尽可能小的预测模式,但是对于完整的大分块下,这种J就是最小的吗?是不是要进行更微观的搜索呢?
答案是:Yes,进行亚像素搜索!
这个思想类似显微镜调节时,先调粗准焦,再调细准焦一样。
重点看右下角的图,假设我们一开始确定J最小的块是蓝色的块,通过亚像素搜索看看其他四色的块是不是J更小呢。
在这里插入图片描述

2.1.2 计算代价

当我们完成上述的亚像素搜索后,已经基本确定了当前模式(完全模式)下的最佳预测块pred和其运动向量x’,y’.那么我们就可以来开始计算代价了。
如下图,好不容易motion_comp_block返回了结果就是上面的pred,x’,y’。
现在我们拿着这些东西来算代价。
具体计算规则和I帧编码一致请读者参考I帧编码。
在这里插入图片描述

2.2进行对角预测motion_comp_vert(bs,mr,i,j)

其实和完全模式类似,但没有完全模式复杂。剩下预测模式请读者自行探索。
这里多提一嘴,如何来评判这个块适合哪种模式呢?见下图!(很重要)
在这里插入图片描述

3.子块预测

首先,并不是所有的预测模式中都有子块预测,针对对角预测模式才有子块预测。
这里多了个大块变小块的过程。其他具体操作和大块预测一致。
在这里插入图片描述

4.小结

本章主要介绍了Matlab源码的帧间编码流程。流程相对复杂,但总体来说就是做了五件事:

  1. 预测
  2. 比较不同预测的代价
  3. 比较不同模式的代价
  4. 块编码
  5. 比特流拼接

其中预测部分和比较部分是帧间编码的精髓所在,这也是帧间预测的难点!!

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值