1423 字
7 分钟
CDAF 与 PDAF:两种对焦观测方法

AF 控制器需要观测当前离焦状态,但传感器不能直接读出“焦点距离”。CDAF 从最终图像的清晰度变化间接寻找峰值;PDAF 比较两幅孔径子像的相位,直接估计方向与离焦量。二者看到的是同一个光学问题,却提供不同形式的信息。

CDAF:把清晰度写成一条曲线#

离焦相当于扩大点扩散函数,边缘被摊宽,高频能量随之下降。CDAF(Contrast Detection Auto Focus)通常在 ROI 内计算梯度、Laplacian、带通能量或其他清晰度分数。镜组扫过正确焦点时,分数往往形成一个峰值。

对比度 AF 为什么要扫过焦点

清晰边缘通常带来更高的高频或梯度分数,但单次测量只知道当前清晰度,不知道焦点在前还是在后。

对比度曲线
当前清晰度0.20
离峰值距离0.36

分数低可能是离焦,也可能是墙面本来就没有纹理。对比度 AF 无法仅凭一个低分区分二者。

两种常见 CDAF 清晰度统计#

在灰度 ROI I(x,y)I(x,y) 内,梯度能量可以写成:

S=1Nx,y[(xI)2+(yI)2]S_{\nabla}=\frac{1}{N}\sum_{x,y}\left[(\partial_x I)^2+(\partial_y I)^2\right]

也常使用 Laplacian 方差:

SΔ=Var ⁣(ΔI)S_{\Delta}=\operatorname{Var}\!\left(\Delta I\right)

合焦边缘通常包含更多高频,因此这两个数值往往随清晰度上升。但噪声、锐化和细密重复纹理也会抬高它们,所以工程实现还会结合亮度、噪声估计、频带限制与峰形判断。

单个分数只表示“现在有多清晰”,并不告诉算法峰值位于当前位置的哪一侧。相同的低分既可能来自严重离焦,也可能来自一面本来就没有纹理的墙。因此 CDAF 必须结合试探移动、历史趋势和置信度,而不能把低分直接等同于离焦。

清晰度分数容易被什么污染#

  • 噪声和过强锐化会制造虚假高频;
  • 主体运动与长曝光会把运动模糊混入离焦;
  • 重复纹理可能形成多个局部峰值;
  • AE、降噪或锐化跨帧突变会改变分数尺度;
  • ROI 内同时存在多个物距时,曲线可能不再是单峰。

所以工业实现通常在较稳定的统计通路上计算分数,并同时检查亮度、纹理量、运动和峰形。

PDAF:比较左右孔径子像#

PDAF(Phase Detection Auto Focus)让成对采样观察出瞳的不同部分。合焦时,两幅子像对齐;离焦时,它们发生相对平移。位移的符号对应焦前或焦后,幅度在标定范围内近似反映需要移动的镜组量。

若左右子像分别为 L(x)L(x)R(x)R(x),可用归一化互相关寻找相对位移:

δ^=argmaxδ x(L(x)Lˉ)(R(x+δ)Rˉ)σLσR+ε\hat{\delta}=\arg\max_{\delta}\ \frac{\sum_x (L(x)-\bar L)(R(x+\delta)-\bar R)}{\sigma_L\sigma_R+\varepsilon}

经过镜头与传感器标定后,离焦控制量可在局部范围内近似为:

efocusk(δ^δ0)e_{\mathrm{focus}} \approx k\left(\hat{\delta}-\delta_0\right)

δ0\delta_0 是合焦时的残余偏置,kk 把像素位移映射到镜组运动量。正负号究竟代表向近端还是远端移动,取决于左右子像顺序、坐标方向与马达定义,必须通过标定固定,不能脱离具体系统硬套。

PDAF 怎样一次判断离焦方向

成对的相位采样观察镜头孔径的不同部分;两幅子像的相对位移给出离焦量与移动方向。

估计离焦+0.42
相位置信度64%

镜组向远端移动。低纹理、纹理方向不匹配、低照度或遮挡会让相位峰不可靠,系统通常回退到对比度确认。

下面的 NumPy 示例同时演示 Laplacian 方差和一维相位位移估计,不依赖 OpenCV 或 SciPy:

import numpy as np
def laplacian_variance(image: np.ndarray) -> float:
image = image.astype(np.float64)
lap = (
-4.0 * image[1:-1, 1:-1]
+ image[:-2, 1:-1] + image[2:, 1:-1]
+ image[1:-1, :-2] + image[1:-1, 2:]
)
return float(np.var(lap))
def estimate_shift(left: np.ndarray, right: np.ndarray, max_shift=8) -> int:
left = (left - left.mean()) / (left.std() + 1e-9)
right = (right - right.mean()) / (right.std() + 1e-9)
shifts = np.arange(-max_shift, max_shift + 1)
scores = []
for shift in shifts:
shifted = np.roll(right, shift)
valid = slice(max_shift, -max_shift)
scores.append(np.mean(left[valid] * shifted[valid]))
11 collapsed lines
return int(shifts[np.argmax(scores)])
rng = np.random.default_rng(7)
image = np.zeros((32, 32))
image[:, 16:] = 1.0
noisy_image = image + rng.normal(0, 0.02, image.shape)
left = np.sin(np.linspace(0, 5 * np.pi, 128))
right = np.roll(left, 3)
print("Laplacian 方差:", laplacian_variance(noisy_image))
print("估计对齐位移:", estimate_shift(left, right), "px")

示例用理想边缘和循环平移解释观测量,没有模拟真实点扩散函数、相位像素遮罩、边界缺失、亚像素拟合或周期纹理歧义。互动组件同样强调趋势,不代表相机内部统计链路的完整实现。

与 CDAF 相比,PDAF 的关键优势不是“分数更高”,而是一次观测就可能提供方向。控制器无需先向两侧试探,就能做较大的预测移动。

但相位信息也有盲区。检测基线若主要对水平位移敏感,缺少相应方向纹理时相关峰会变弱;低照、遮挡、周期图案、相位像素缺陷和镜头像差也会带来错误匹配。系统必须输出置信度,而不能在每一帧都强行给出方向。

两种方法怎样互补#

特性CDAFPDAF
主要观测最终图像的清晰度成对子像的相对相位
单次方向信息通常没有通常有
接近峰值后的确认直接、直观依赖标定与残差模型
额外硬件要求较低相位像素或专用 AF 模块
常见弱点拉风箱、局部峰、低纹理纹理方向、低照、标定偏差

混合 AF 的常见策略是:PDAF 在高置信度时预测方向和步长,让镜组快速接近;接近目标后缩小动作,再用 CDAF 峰值或相位残差确认。PDAF 置信度下降时,系统退回小步 CDAF 搜索,而不是继续执行不可靠的大动作。

标定决定 PDAF 数值能否用于控制#

相位位移并不天然等于马达步数。系统要在不同焦距、物距、光圈、颜色光源和温度下建立映射,并校正左右子像偏置、相位像素遮罩和镜头场曲。量产设备还要处理个体差异。

因此“测出相位”只是观测层的开始。下一篇将继续讨论:如何把观测转换成搜索步长、镜组命令和稳定的连续追焦行为。

CDAF 与 PDAF:两种对焦观测方法
https://cloudsir.top/posts/how-cdaf-and-pdaf-work/
作者
CloudSir
发布于
2026-08-25
许可协议
CC BY-NC-SA 4.0
AWB 自动白平衡系统:从光源估计到闭环控制
对焦搜索、马达控制与连续追焦