4、帧间预测与运动估计优化:运动估计搜索算法与搜索范围步长优化

运动估计,说白了就是找块。在编码当前块的时候,去参考帧里找一个最像它的块,然后把两者之间的位移记下来——这就是运动矢量。这个找块的过程,就是搜索。

搜索算法选得好不好,直接影响编码速度和压缩率。我见过不少团队,为了省事直接上全搜索,结果编码慢得没法用;也有人为了追求速度,用了个太粗糙的搜索,码率蹭蹭往上涨。今天咱们就把这块掰开揉碎了讲清楚。

4.1 三种主流搜索算法:全搜索、TZSearch、菱形搜索

先看一张对比表,心里有个底:

算法 搜索策略 计算复杂度 压缩效率 适用场景
全搜索(Full Search) 遍历搜索窗口内所有候选点 极高 理论最优 离线编码、学术基准
TZSearch 菱形+光栅+细化多级混合 中等 接近全搜索 HEVC/H.265 默认推荐
菱形搜索(DS) 大菱形→小菱形逐步收敛 低 良好 实时编码、低功耗设备

4.2 全搜索:简单粗暴,但代价太高

全搜索的逻辑很简单:搜索范围设成 ±64,那就把 129×129 个位置全部算一遍 SAD。每个位置都要做一次匹配计算,复杂度是 O(N²)。

我记得刚入行那会儿,有个项目要做 4K 实时编码,架构师拍脑袋选了全搜索。结果呢?编码一帧要 3 秒多,完全没法用。后来改成 TZSearch,帧率直接翻了 10 倍,画质几乎没掉。

避坑指南: 我曾经见过有人把全搜索用在移动端直播编码上,CPU 直接跑满 100%,手机烫得能煎鸡蛋。全搜索只适合做离线分析或学术对比,千万别在生产环境里用。

4.3 TZSearch:HEVC 的默认王者

TZSearch 是 HEVC 参考软件 HM 里的默认搜索算法。它为什么强?因为它用了多级混合策略:

  1. 第一步:菱形/正方形栅格搜索——用大步长快速定位到大致区域
  2. 第二步:细化搜索——在第一步找到的最佳点周围,用小步长做菱形或正方形细化
  3. 第三步:光栅搜索(可选)——如果前两步的结果不够好,再补一个全光栅扫描兜底
  4. 第四步:星形搜索——在最终点周围做 8 方向或 16 方向验证

说白了,TZSearch 先用粗搜缩小范围,再用细搜精确定位。这个思路跟人类找东西很像——先扫一眼大概位置,再凑近了仔细看。

我个人习惯把 TZSearch 的 SearchRange 设成 64,StarSearch 开启,RasterSearch 设成 5。这样在大多数场景下,压缩率只比全搜索低 0.5% 左右,但速度快了 20 倍以上。

小技巧: 在 x265 里,TZSearch 是默认开启的。你可以通过 --me tz 显式指定。如果遇到运动特别剧烈的场景,把 --subme 从 4 提到 7,TZSearch 的细化步数会增加,能找回不少码率。

4.4 菱形搜索:轻量级选手

菱形搜索(Diamond Search)是经典快速搜索算法。它用一个大菱形模板(步长 2)做粗搜,找到最佳点后换成小菱形模板(步长 1)做细搜,直到收敛。

它的优点是计算量小,适合实时场景。但缺点也很明显——容易掉进局部最优。你想想看,如果真实运动矢量在搜索窗口边缘,菱形搜索可能还没走到那儿就停了。

我在做嵌入式编码器的时候用过菱形搜索。当时芯片的算力只有 200MIPS,TZSearch 跑不动,只能用菱形搜索。为了弥补精度损失,我把搜索范围从 ±32 扩大到了 ±48,效果好了不少。

4.5 搜索范围与步长优化

搜索范围(Search Range)和步长(Step Size)是运动估计的两个关键参数。它们直接影响编码质量和速度。

4.5.1 搜索范围怎么设?

搜索范围越大,能捕捉到的运动越剧烈,但计算量也越大。我一般按分辨率来设:

分辨率 推荐搜索范围 说明
480p 及以下 ±16 ~ ±32 运动幅度小,范围够用
720p ±32 ~ ±48 中等运动,平衡速度和精度
1080p ±48 ~ ±64 高清场景,建议用 64
4K 及以上 ±64 ~ ±128 运动剧烈时用 128,一般 64 够用
核心原则: 搜索范围不是越大越好。超过实际运动范围的部分,全是无效计算。你可以通过分析视频的运动向量分布来动态调整搜索范围——运动小的时候缩小范围,运动大的时候扩大范围。

4.5.2 步长怎么优化?

步长决定了搜索的粒度。步长越小,搜索越精细,但次数也越多。TZSearch 的步长是自适应的——粗搜阶段步长大,细搜阶段步长小。

我建议你关注这几个点:

  • 粗搜步长: 一般用 2 的幂次(1, 2, 4, 8, 16...),这样能快速覆盖大范围
  • 细搜步长: 固定为 1,确保亚像素精度
  • 提前终止阈值: 如果当前 SAD 已经小于某个阈值(比如 256),直接停止搜索。这个技巧在平坦区域能省下大量计算

我曾经优化过一个监控视频编码器。场景大部分是静止的,只有偶尔有人走动。我把提前终止阈值设成 128,结果 80% 的块在第一步就停了,整体编码速度提升了 3 倍,码率只增加了 1%。

4.6 运动估计搜索算法核心流程

下面这张图展示了 TZSearch 的完整流程,我建议你仔细看看:

TZSearch 运动估计搜索流程 开始搜索 步骤1:菱形/正方形栅格搜索 大步长(2,4,8,16...)快速定位 找到更好点? 是 步骤2:细化搜索 小步长(1)菱形细化 否 步骤3:光栅搜索 全光栅扫描兜底 步骤4:星形搜索 8方向/16方向最终验证 输出最佳运动矢量 说明: TZSearch 通过多级混合策略,在搜索精度和计算复杂度之间取得平衡。 粗搜快速定位,细搜精确定位,光栅搜索兜底防止陷入局部最优。

4.7 实战建议:怎么选?怎么调?

说了这么多,到底怎么选?我给你几个实际建议:

  • 离线编码/高质量场景: 用 TZSearch,搜索范围 ±64,开启光栅搜索和星形搜索。压缩率接近全搜索,速度能接受。
  • 实时编码/直播场景: 用 TZSearch 但关闭光栅搜索,搜索范围缩小到 ±32。速度能快 30%,画质损失很小。
  • 低功耗/嵌入式场景: 用菱形搜索,搜索范围 ±48。配合提前终止阈值,能在有限算力下跑出不错的效果。
  • 学术对比/基准测试: 用全搜索,搜索范围 ±64。但记住,这只是为了拿参考数据,别用在产品里。
调参口诀: 范围看分辨率,算法看场景,步长看精度,终止看平坦。这四个维度调好了,运动估计这块基本就稳了。

嗯,运动估计搜索这块内容不少,但核心就三个字——快、准、省。快是速度,准是精度,省是算力。三者不可兼得,但 TZSearch 给了我们一个接近最优的平衡点。你在实际项目中,多跑几组对比测试,找到最适合你场景的参数组合就行。