4、帧间预测与运动估计优化:运动估计搜索算法与搜索范围步长优化
运动估计,说白了就是找块。在编码当前块的时候,去参考帧里找一个最像它的块,然后把两者之间的位移记下来——这就是运动矢量。这个找块的过程,就是搜索。
搜索算法选得好不好,直接影响编码速度和压缩率。我见过不少团队,为了省事直接上全搜索,结果编码慢得没法用;也有人为了追求速度,用了个太粗糙的搜索,码率蹭蹭往上涨。今天咱们就把这块掰开揉碎了讲清楚。
4.1 三种主流搜索算法:全搜索、TZSearch、菱形搜索
先看一张对比表,心里有个底:
| 算法 | 搜索策略 | 计算复杂度 | 压缩效率 | 适用场景 |
|---|---|---|---|---|
| 全搜索(Full Search) | 遍历搜索窗口内所有候选点 | 极高 | 理论最优 | 离线编码、学术基准 |
| TZSearch | 菱形+光栅+细化多级混合 | 中等 | 接近全搜索 | HEVC/H.265 默认推荐 |
| 菱形搜索(DS) | 大菱形→小菱形逐步收敛 | 低 | 良好 | 实时编码、低功耗设备 |
4.2 全搜索:简单粗暴,但代价太高
全搜索的逻辑很简单:搜索范围设成 ±64,那就把 129×129 个位置全部算一遍 SAD。每个位置都要做一次匹配计算,复杂度是 O(N²)。
我记得刚入行那会儿,有个项目要做 4K 实时编码,架构师拍脑袋选了全搜索。结果呢?编码一帧要 3 秒多,完全没法用。后来改成 TZSearch,帧率直接翻了 10 倍,画质几乎没掉。
4.3 TZSearch:HEVC 的默认王者
TZSearch 是 HEVC 参考软件 HM 里的默认搜索算法。它为什么强?因为它用了多级混合策略:
- 第一步:菱形/正方形栅格搜索——用大步长快速定位到大致区域
- 第二步:细化搜索——在第一步找到的最佳点周围,用小步长做菱形或正方形细化
- 第三步:光栅搜索(可选)——如果前两步的结果不够好,再补一个全光栅扫描兜底
- 第四步:星形搜索——在最终点周围做 8 方向或 16 方向验证
说白了,TZSearch 先用粗搜缩小范围,再用细搜精确定位。这个思路跟人类找东西很像——先扫一眼大概位置,再凑近了仔细看。
我个人习惯把 TZSearch 的 SearchRange 设成 64,StarSearch 开启,RasterSearch 设成 5。这样在大多数场景下,压缩率只比全搜索低 0.5% 左右,但速度快了 20 倍以上。
--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 的完整流程,我建议你仔细看看:
4.7 实战建议:怎么选?怎么调?
说了这么多,到底怎么选?我给你几个实际建议:
- 离线编码/高质量场景: 用 TZSearch,搜索范围 ±64,开启光栅搜索和星形搜索。压缩率接近全搜索,速度能接受。
- 实时编码/直播场景: 用 TZSearch 但关闭光栅搜索,搜索范围缩小到 ±32。速度能快 30%,画质损失很小。
- 低功耗/嵌入式场景: 用菱形搜索,搜索范围 ±48。配合提前终止阈值,能在有限算力下跑出不错的效果。
- 学术对比/基准测试: 用全搜索,搜索范围 ±64。但记住,这只是为了拿参考数据,别用在产品里。
嗯,运动估计搜索这块内容不少,但核心就三个字——快、准、省。快是速度,准是精度,省是算力。三者不可兼得,但 TZSearch 给了我们一个接近最优的平衡点。你在实际项目中,多跑几组对比测试,找到最适合你场景的参数组合就行。