双摄虚化原理:双目视差、深度图生成、虚化强度控制

人像模式的核心,说白了就是让手机拍出单反大光圈的效果。背景虚化,主体清晰。但手机镜头物理光圈就那么小,怎么做到的?

答案是双摄。用两颗摄像头模拟人眼,通过计算来“猜”出场景的深度信息。我最早接触这个模块是在高通骁龙845平台,那时候算法还比较粗糙,抠图经常翻车。现在好多了,但核心原理没变。

2.1 双目视差:人眼怎么判断远近

你想想看,为什么你闭上一只眼,就很难判断距离?因为人眼靠左右眼看到的图像差异来感知深度。这个差异,就叫视差。

双摄虚化也是这个道理。主摄和副摄之间有一定距离(基线),它们同时拍下同一场景。近处的物体,在两颗摄像头画面中的位置偏移大;远处的物体,偏移小。

核心公式(简化版):

深度 ∝ 基线长度 × 焦距 / 视差值

基线越长,深度分辨率越高。但手机厚度有限,所以这是个妥协的艺术。

我在项目中遇到过一个问题:基线太短,近处和远处的视差区别很小,深度图就糊成一片。后来我们通过算法插值勉强补救,但物理限制摆在那里。

物体距离 视差值 深度估计精度
近(0.3m) 大(几十像素) 高
中(1m) 中等 中等
远(5m+) 小(几个像素) 低

嗯,这里要注意:视差计算依赖特征匹配。如果场景是纯色墙壁,没有纹理,算法就抓瞎了。所以有些手机在暗光下虚化效果差,不全是噪声问题,纹理丢失也是原因。

2.2 深度图生成:从视差到灰度图

有了左右眼的视差数据,下一步就是生成深度图。深度图是一张灰度图,每个像素的灰度值代表该点的深度。越亮表示越近,越暗表示越远。

生成流程大致如下:

  1. 图像校正:把左右图对齐到同一平面,消除镜头畸变和安装误差。
  2. 立体匹配:在左图上选一个像素,到右图同一行上找最相似的点。这个搜索范围叫“视差搜索范围”。
  3. 代价计算:用SAD(差和)或SSD(平方差和)衡量两个像素块的相似度。
  4. 视差优化:用全局或半全局匹配算法(如SGM)平滑视差图,去除噪点。
  5. 深度映射:把视差值转换成深度值,输出8位或16位深度图。

我的经验:立体匹配这一步最耗时。高通平台上有硬件加速模块(ISP中的深度引擎),可以大幅降低计算延迟。我建议你优先使用硬件加速,而不是纯CPU计算,否则帧率会掉到个位数。

深度图的质量直接决定虚化效果。如果深度图边缘模糊,虚化后的主体边缘就会有一圈“光晕”。我曾经调试过一个案子,人像头发边缘总是虚化不干净,最后发现是立体匹配的窗口大小设得太大了,导致深度图在边缘处平滑过度。

// 伪代码:立体匹配核心逻辑
for each pixel (x, y) in left_image:
    min_cost = INF
    best_disparity = 0
    for d in disparity_range:
        cost = SAD(left_image[x][y], right_image[x-d][y])
        if cost < min_cost:
            min_cost = cost
            best_disparity = d
    disparity_map[x][y] = best_disparity

这段代码看着简单,实际工程里要考虑的东西多得多。比如遮挡处理、亚像素插值、一致性检查。高通平台提供了完整的Depth API,但理解底层原理对调试很有帮助。

2.3 虚化强度控制:从f/1.4到f/16的模拟

深度图有了,怎么控制虚化程度?

虚化强度本质上是一个模糊半径。模糊半径越大,背景越糊。但模糊半径不是随便设的,它要跟深度值挂钩。

我习惯的做法是:

  • 设定一个“焦平面”深度值。在这个深度上的物体保持清晰。
  • 偏离焦平面越远,模糊半径越大。
  • 模糊半径的增长曲线可以是线性的,也可以是非线性的(模拟真实镜头的光学特性)。

注意:虚化强度不是越大越好。强度过高,会出现“纸片人”效果——主体像贴在背景上的贴纸。这是因为深度图在边缘处不够精确,导致主体和背景的过渡不自然。

高通平台上的虚化强度控制通常通过以下几个参数调节:

参数名 作用 典型值范围
focal_distance 焦平面深度 0.5m - 5.0m
blur_strength 整体虚化强度 0.0 - 1.0
bokeh_shape 光斑形状(圆形/六边形) 0 / 1
transition_smooth 焦平面过渡平滑度 0.0 - 1.0

我个人习惯把transition_smooth设得高一些,这样主体到背景的过渡更自然,不会出现明显的“一刀切”感。

还有一个容易被忽略的点:前景虚化。真实镜头在焦平面前面的物体也会虚化,但很多手机算法只做背景虚化。高通平台支持前景虚化,但需要更精确的深度图。我建议在实现时至少保留这个选项,用户体验会好很多。

双摄虚化核心流程 左摄像头 右摄像头 图像校正 立体匹配 深度图生成 虚化渲染 关键:深度图质量决定虚化效果 立体匹配的精度直接影响边缘过渡自然度

最后说一句,虚化强度控制不是单纯调一个滑块。它跟场景内容、光照条件、人脸检测结果都有关系。我建议你在实现时做一个自适应策略:人脸区域强制清晰,背景按深度渐变模糊,过渡区用高斯金字塔做多尺度融合。这样出来的效果才自然。