1552 字
8 分钟
对焦搜索、马达控制与连续追焦

观测层给出清晰度分数或相位离焦量之后,AF 仍未完成。控制器还要选择搜索方向、安排步长、驱动镜组、等待机械稳定,再用下一帧确认结果。连续追焦则必须在这个闭环外再加一层主体运动预测和状态管理。

没有方向时怎样搜索峰值#

CDAF 只知道当前位置的清晰度。最直接的方法是试探移动:若分数上升就沿同一方向继续,若下降则反向并缩小步长。它本质上是在镜组位置轴上做一维爬山搜索。

爬山搜索怎样找到清晰度峰值

比较当前位置两侧的清晰度,向更高方向移动;越过峰值后缩小步长,逐渐收敛。

最终位置0.750
峰值误差0.030

真实场景可能有多个局部峰值;镜组回差、画面运动和曝光变化也会污染相邻帧的分数比较。

较大的初始步长能缩短行程,却可能直接越过窄峰;步长太小则会拖慢锁焦。常见调度方式是粗搜、细搜和确认三阶段:

  1. 粗搜快速确定峰值区间;
  2. 细搜在峰值两侧缩小步长;
  3. 确认阶段等待镜组与画面稳定,检查分数没有继续改善。

PDAF 可以把预测位置作为粗搜起点,但仍需要闭环确认。任何一次观测都可能受运动、噪声或遮挡污染。

把当前位置写成 xkx_k,搜索方向为 dk{1,+1}d_k\in\{-1,+1\},步长为 hkh_k。一种简化爬山更新是:

xk+1=clip(xk+dkhk),(dk+1,hk+1)={(dk,hk),Sk+1>Sk+τ(dk,βhk),Sk+1Sk+τx_{k+1}=\operatorname{clip}(x_k+d_kh_k),\qquad (d_{k+1},h_{k+1})= \begin{cases} (d_k,h_k), & S_{k+1}>S_k+\tau \\ (-d_k,\beta h_k), & S_{k+1}\le S_k+\tau \end{cases}

τ\tau 是避免追随微小噪声的改善阈值,0<β<10<\beta<1 用于反向后缩小步长。粗到细搜索只是对 hkh_k 的调度:先用大步长定位峰值区间,再缩小步长确认,而不是对所有马达位置等间隔穷举。

下面的 NumPy 示例在一条带少量噪声的教学曲线上执行粗到细爬山,并在误差进入死区后保持位置:

import numpy as np
rng = np.random.default_rng(12)
def measure(position: float) -> float:
peak = np.exp(-0.5 * ((position - 0.67) / 0.18) ** 2)
return float(peak + rng.normal(0.0, 0.002))
position, direction, step = 0.15, 1.0, 0.12
score = measure(position)
for iteration in range(18):
candidate = float(np.clip(position + direction * step, 0.0, 1.0))
candidate_score = measure(candidate)
if candidate_score > score + 0.003:
position, score = candidate, candidate_score
else:
direction *= -1.0
step *= 0.5
if step < 0.006:
break
2 collapsed lines
print(f"position={position:.3f}, score={score:.3f}, iterations={iteration + 1}")

这里假设目标函数近似单峰,且每次命令后镜组已经稳定。真实系统会遇到回差、测量延迟、主体移动和 ROI 切换,不能把一次分数下降简单等同于“已经越过焦点”。

马达命令不等于镜组位置#

镜组是有摩擦和惯性的机械系统。控制器需要面对:

  • 回差:从不同方向接近同一命令位置,实际落点不同;
  • 迟滞与稳定时间:命令结束后镜组仍可能振动;
  • 姿态影响:重力方向改变负载和响应;
  • 温度漂移:材料和执行器特性随温度变化;
  • 位置限制:近端与远端必须减速,避免撞限位;
  • 焦点呼吸:镜组移动会改变视角,录像中尤其明显。

工程上常让最终确认从固定方向逼近,以减小回差不确定性;大步移动后还会留出稳定帧,避免把机械振动当成焦点变化。

ROI 变化会改变搜索目标#

搜索并不是在一条永远不变的曲线上前进。主体、背景和遮挡物对应不同峰值,ROI 权重一变,控制器看到的目标函数也随之变化。

对焦框选错,算法会清晰地对错地方

前景主体与背景各自拥有清晰度峰值;ROI 权重决定哪一个峰值主导搜索。

ROI 综合分数0.45
当前更清晰主体
对焦区域

这张大光圈样片本身具有浅景深。滑杆模拟镜组位置,预览模糊量由选中 ROI 的教学分数驱动;真实离焦卷积不会是均匀 CSS blur。

因此 AF 必须把“分数下降”区分成多种原因:主体真的离开焦面、主体被遮挡、ROI 跳到了背景、曝光变化,或者只是测量噪声。没有主体身份和时序信息,控制器很容易追着背景峰值来回移动。

连续追焦需要状态机#

实用的连续 AF 通常不会每帧都立即驱动镜组,而是在几个状态间切换:

IDLE → ACQUIRE → LOCKED → TRACKING
↑ ↓ ↓
└──── LOST / REACQUIRE
  • ACQUIRE:允许较大步长,尽快建立初始焦点;
  • LOCKED:主体稳定时设置死区,忽略小幅分数波动;
  • TRACKING:根据连续离焦量和主体速度平滑预测;
  • LOST:置信度骤降时先保持距离,避免立即拉风箱;
  • REACQUIRE:扩大搜索范围,但限制切换目标的速度。

状态切换通常要满足连续多帧条件。进入跟踪可以比退出锁定更谨慎,形成迟滞,从而避免阈值附近反复跳转。

死区、迟滞与跟踪状态更新#

设滤波后的离焦量为 e^t\hat e_t。死区控制可以写成:

ut={0,e^t<TholdKe^t,e^tTmove,Tmove>Tholdu_t= \begin{cases} 0, & |\hat e_t|<T_{\mathrm{hold}} \\ K\hat e_t, & |\hat e_t|\ge T_{\mathrm{move}} \end{cases},\qquad T_{\mathrm{move}}>T_{\mathrm{hold}}

两个不同阈值形成迟滞:进入移动要跨过较大的 TmoveT_{\mathrm{move}},已经移动后则要降到较小的 TholdT_{\mathrm{hold}} 才停。简单的一阶预测状态还可写成:

x^tt1=x^t1+v^t1Δtx^t=x^tt1+αct(ztx^tt1)v^t=(1γ)v^t1+γx^tx^t1Δt\begin{aligned} \hat x_{t|t-1} &= \hat x_{t-1}+\hat v_{t-1}\Delta t \\ \hat x_t &= \hat x_{t|t-1}+\alpha c_t(z_t-\hat x_{t|t-1}) \\ \hat v_t &= (1-\gamma)\hat v_{t-1}+\gamma\frac{\hat x_t-\hat x_{t-1}}{\Delta t} \end{aligned}

ztz_t 是本帧焦点观测,ctc_t 是置信度。置信度下降时,校正项自动减小,系统更依赖上一时刻的速度预测;连续低置信度则应进入 LOST,而不是无限外推。该模型只用于解释状态更新,实际连续 AF 还可能融合主体检测、陀螺仪、深度与镜组动力学。

速度、稳定和观感的取舍#

照片 AF 常追求最短锁焦时间;视频 AF 更在意轨迹是否自然。过强的预测会在主体突然停止时过冲,过大的死区又会让焦点落后。工程调参需要同时观察:

  • 首次锁定时间与成功率;
  • 稳态焦点抖动和重复定位误差;
  • 匀速、加速和突然反向运动的跟随延迟;
  • 短暂遮挡时是否保持原主体;
  • 主体切换是否符合构图意图;
  • 镜组速度、噪声、功耗和焦点呼吸。

一个可靠的 AF 控制器不会把每帧估计都当成绝对真相。它结合观测置信度、镜组模型、主体轨迹和历史状态,决定此刻应该快速移动、微调、保持,还是承认信息不足并等待下一帧。

对焦搜索、马达控制与连续追焦
https://cloudsir.top/posts/how-autofocus-search-and-tracking-work/
作者
CloudSir
发布于
2026-08-25
许可协议
CC BY-NC-SA 4.0
CDAF 与 PDAF:两种对焦观测方法
人像、风光、运动与夜景:四类实拍决策