2157 字
11 分钟
AE 怎样稳定收敛?从曝光闭环到防频闪

测光模块给出曝光误差后,AE 还不能直接把它全部写进传感器。当前统计通常来自上一帧,新的寄存器命令又可能隔一到数帧才生效;控制过于激进会在目标两侧振荡,控制过慢则会让用户看着画面长时间变亮或变暗。

从静态误差到离散时间控制#

若用 EnE_n 表示第 nn 帧的曝光状态,最简单的一阶控制是:

En+1=En+α(EtEn)E_{n+1}=E_n+\alpha(E_t-E_n)

α\alpha 越大,理论收敛越快。但真实统计含噪声,执行路径含延迟,目标本身还可能因 ROI 变化而移动。

曝光为什么不能一步跳到目标

反馈速度越快,亮度响应越及时;但测量噪声、延迟和场景变化会让激进控制产生闪烁。

输出亮度 / 帧
第 14 帧亮度0.64
剩余误差0.007

教学曲线是一阶控制器。真实 AE 还要处理统计延迟、曝光生效延迟、上下行速度不对称和场景切换检测。

量产系统常组合以下策略:

  • 目标附近设置死区,忽略不影响观感的小误差;
  • 限制每帧最大 EV 步长,防止画面突然跳变;
  • 分别设置变亮与变暗速度,例如优先快速保护高光;
  • 检测大幅场景变化,临时从稳定模式切换到快速模式;
  • 对测光统计做时域滤波,但在镜头切换时重置历史;
  • 根据命令生效帧号匹配统计,避免把旧曝光的结果归因于新命令。

若传感器命令延迟为 dd 帧,控制器实际面对的是 EndE_{n-d} 的结果。忽略该延迟时,提高 α\alpha 很容易导致过冲和周期性闪烁。调参不能只看静态终值,还要观察完整的逐帧波形。

从误差到可执行命令#

把测光篇得到的 EV 误差记为 ene_n。死区先消除目标附近的小幅扰动,再用最大步长 Δmax\Delta_{max} 限制单帧变化:

endz={0,en<δensgn(en)δ,enδe_n^{dz}=\begin{cases} 0,& |e_n|<\delta\\ e_n-\operatorname{sgn}(e_n)\delta,& |e_n|\ge\delta \end{cases}Δun=clip(αendz,Δdown,Δup),un+1=clip(un+Δun,umin,umax)\Delta u_n=\operatorname{clip}(\alpha e_n^{dz},-\Delta_{down},\Delta_{up}), \qquad u_{n+1}=\operatorname{clip}(u_n+\Delta u_n,u_{min},u_{max})

上行和下行可使用不同限制,例如突然出现大面积高光时允许更快降低曝光。若命令延迟为 dd 帧,第 nn 帧图像实际由较早的命令产生:

Ym,n=P(und,Ln)+ηnY_{m,n}=P(u_{n-d},L_n)+\eta_n

PP 表示场景照度 LnL_n 与传感器执行路径,ηn\eta_n 表示统计噪声。实现中应为命令附带预计生效帧号,把返回统计与真正生成它的命令对应起来,而不是默认“刚写入就生效”。

人工照明下,理想快门 tt^* 还要量化到光强周期 TfT_f 的整数倍:

Tf=12fmains,k=max ⁣(1,tTf),tq=kTfT_f=\frac{1}{2f_{mains}},\qquad k=\max\!\left(1,\left\lfloor\frac{t^*}{T_f}\right\rfloor\right),\qquad t_q=kT_f

t<Tft^*<T_f 时,产品也可能使用与行读出和灯光相位共同验证过的短快门表,而不是强制延长到一个周期。量化后未满足的曝光倍率可由模拟增益补齐:

Gq=GttqG_q=G^*\frac{t^*}{t_q}

下面的 NumPy 示例模拟了两帧命令延迟、死区、非对称步长,以及 50 Hz 下的安全快门量化。它打印每一帧的观测与新命令,便于观察闭环而不是只看最终值。

from collections import deque
import numpy as np
frames = 18
target = 0.30
scene = np.r_[np.full(5, 0.30), np.full(frames - 5, 0.075)]
delay_frames = 2
deadband_ev = 0.06
alpha = 0.55
max_up_ev, max_down_ev = 0.45, 0.70
command_ev = 0.0
pipeline = deque([command_ev] * delay_frames)
def controller_step(error_ev):
if abs(error_ev) < deadband_ev:
return 0.0
error_after_deadband = error_ev - np.sign(error_ev) * deadband_ev
return float(np.clip(alpha * error_after_deadband, -max_down_ev, max_up_ev))
22 collapsed lines
def quantize_for_mains(ideal_shutter_s, mains_hz):
period = 1.0 / (2.0 * mains_hz)
if ideal_shutter_s < period:
return ideal_shutter_s # 短快门表在真实产品中需另行标定
return max(1, np.floor(ideal_shutter_s / period)) * period
for n in range(frames):
applied_ev = pipeline.popleft()
measured = np.clip(scene[n] * 2.0 ** applied_ev, 1e-4, 1.0)
error_ev = np.log2(target / measured)
command_ev += controller_step(error_ev)
command_ev = float(np.clip(command_ev, -4.0, 6.0))
pipeline.append(command_ev)
ideal_shutter = (1.0 / 250.0) * 2.0 ** max(command_ev, 0.0)
safe_shutter = quantize_for_mains(ideal_shutter, mains_hz=50.0)
residual_gain = ideal_shutter / safe_shutter
print(
f"{n:02d}: Y={measured:.3f}, error={error_ev:+.2f} EV, "
f"cmd={command_ev:+.2f} EV, t={safe_shutter*1e3:.1f} ms, "
f"gain×={residual_gain:.2f}"
)

为保持代码独立可读,示例用 Y2uY\propto 2^u 的无饱和线性场景模型,也没有加入传感器寄存器离散值、增益上下界、滚动快门行相位或自动灯频检测。它适合验证控制顺序,不能直接作为量产控制器。

曝光量必须分配给硬件参数#

控制器通常先得到期望曝光乘积,再由 exposure program 分配给光圈 NN、快门时间 tt 和总增益 GG。简化关系可写为:

HtN2GH\propto \frac{t}{N^2}G

手机常使用固定光圈,于是主要在快门与增益之间选择。相同输出亮度并不代表相同画质:长快门积累更多光子但拖长运动轨迹,高增益有助于缩短快门却会放大噪声,并更早消耗高光余量。

快门、增益与防频闪怎样取舍

相同曝光量可以由更长快门或更高增益得到;人工光源下还要把快门吸附到电网半周期。

曝光量指标36.0
50 Hz 防频闪快门20.00 ms
市电频率

防频闪常按 50 Hz 的 10 ms 或 60 Hz 的 8.33 ms 半周期约束曝光。LED PWM 可能使用完全不同的频率,需额外检测。

一个常见分配顺序是:亮场先保持低增益并缩短快门;光线变暗后延长快门,直到运动或帧率上限;再提高模拟增益,最后才使用数字增益。实际顺序会根据录像、运动检测、光学防抖、人脸和夜景模式调整。

模拟增益与数字增益也不能简单合并。模拟增益发生在 ADC 前,可能改善量化利用率,但同时放大读出链前部噪声;数字增益发生在采样后,通常不会增加真实光子信噪比。不同传感器还可能在某些增益点切换转换增益模式,使噪声曲线出现台阶。

帧率给快门设置硬上限#

30 fps 的帧周期约为 33.3 ms,快门不能无限延长而仍维持同样帧率。曝光还要预留传感器读出与 blanking 时间。低照度下,系统必须在以下选择间明确优先级:

  • 保持帧率并提高增益;
  • 降低帧率以允许更长曝光;
  • 接受较暗画面,让后续降噪与 Tone Mapping 处理;
  • 切换到多帧夜景模式,不再维持普通实时预览约束。

录像通常要求帧率稳定,视频会议还重视运动清晰度;静态拍照则可结合陀螺仪和主体运动估计,使用更长曝光换取信噪比。

为什么人工照明会频闪#

许多交流灯具的光强随电网周期变化。50 Hz 市电常产生 100 Hz 光强波动,半周期为 10 ms;60 Hz 常产生 120 Hz 波动,半周期约 8.33 ms。若曝光窗口覆盖整数个光强周期,积分能量更稳定:

texpk12fmains,k=1,2,3,t_{exp}\approx k\frac{1}{2f_{mains}},\qquad k=1,2,3,\ldots

因此防频闪模式会把理想快门吸附到安全档位,再用增益补齐剩余曝光误差。吸附本身会让曝光参数离散变化,控制器需要用迟滞避免在两个档位间来回跳。

滚动快门逐行开始与结束曝光。同一帧的不同行若采到灯光波形的不同相位,就会形成横向条带;相邻帧采样相位变化,还会产生整体亮度跳动。

50/60 Hz 不是全部答案#

LED PWM、调光器、显示屏和车灯可能使用与电网无关的频率,甚至具有复杂脉冲波形。只提供“50 Hz / 60 Hz”开关无法覆盖所有场景。更完整的系统会从逐行统计或多帧亮度序列估计频率与相位,再选择快门或同步策略。

检测也会有混叠:采样帧率不足时,不同实际频率可能表现为相同低频变化。因此防频闪测试需要覆盖真实灯具、不同亮度档位、不同帧率与滚动快门读出时间,不能只用理想正弦波仿真。

一套可验证的状态机#

工程实现可将 AE 明确拆成状态:

稳定监视 → 检测场景变化 → 快速搜索
→ 接近目标 → 慢速收敛 → 进入死区
↘ 灯频变化:重新锁定安全快门

每次状态切换都应定义进入条件、退出条件、最大停留帧数和历史统计如何处理。这样比堆叠互相覆盖的速度系数更容易复现问题。

验证清单#

  1. 明暗阶跃场景的收敛时间、过冲和稳态波动;
  2. 曝光命令延迟为 0、1、2 帧时的稳定性;
  3. 上行与下行速度以及场景切换后的连续性;
  4. 静止与运动主体下的快门/增益分配曲线;
  5. 24/25/30/50/60 fps 的最大快门约束;
  6. 50 Hz、60 Hz 和多种 LED PWM 灯具的条带与亮度波动;
  7. 防频闪档位切换处是否因迟滞不足而反复跳档;
  8. HDR 多曝光比例变化时,长短帧是否同时保持稳定。

稳定的 AE 不是追求最快抵达目标,而是在有限帧率、命令延迟、运动、噪声与照明周期之间选择可接受的时间响应。测光决定方向,闭环控制决定过程,曝光分配则决定最终画质成本。

AE 怎样稳定收敛?从曝光闭环到防频闪
https://cloudsir.top/posts/how-ae-feedback-and-flicker-control-work/
作者
CloudSir
发布于
2026-08-25
许可协议
CC BY-NC-SA 4.0
AF 自动对焦系统总览:从选主体到驱动镜组
AE 怎样测量亮度?从测光统计到曝光目标