4. 曝光时间控制:曝光时间范围与步长、长曝光与短曝光的权衡、防抖与曝光时间、运动模糊控制策略

曝光时间,说白了就是传感器收集光线的那段时间。你想想看,快门打开多久,光就进来多久。这个参数看似简单,但实际调起来门道很多。我做了这么多年图像算法,踩过的坑有一半都跟曝光时间有关。

4.1 曝光时间的范围与步长

曝光时间不是随便设的。硬件上有限制,算法上也有讲究。先看硬件能支持的范围:

传感器类型 典型最短曝光 典型最长曝光 常见步长
手机CMOS 1/8000 s 1 s 1/3 EV
监控摄像头 1/10000 s 1/30 s 1/6 EV
工业相机 1/100000 s 10 s 1/4 EV
单反相机 1/8000 s 30 s 1/2 EV 或 1/3 EV

这里有个关键点:步长不是越小越好。我见过有人把步长设成 1/100 EV,结果曝光来回跳,画面一闪一闪的。为什么?因为传感器和 ISP 的响应有延迟,步长太细反而造成震荡。

我的习惯: 曝光步长一般取 1/3 EV 或 1/6 EV。1/3 EV 适合快速收敛场景,1/6 EV 适合精细调节场景。别低于 1/8 EV,否则系统会不稳定。

曝光时间的范围还要考虑帧率。比如 30fps 的视频,单帧最长也就 33ms。你设个 50ms 的曝光,那帧率就保不住了。嗯,这里要注意:长曝光模式下帧率会下降,这是物理限制。

4.2 长曝光与短曝光的权衡

长曝光和短曝光,就像天平的两端。长曝光进光多、信噪比高,但容易糊;短曝光抓得稳、动态好,但噪点多。怎么选?看场景。

我总结了一个决策流程,画成图方便你理解:

曝光时间决策流程图 场景光照分析 光照充足? 是 短曝光优先 否 长曝光优先 场景有运动? 是 短曝光 + 增益补偿 否 长曝光 + 多帧降噪

这个流程我用了很多年。核心逻辑就是:先看光照,再看运动。光照够就短曝光,光照不够就长曝光。但如果场景有运动,长曝光就会糊,这时候宁可提增益也别拉长曝光。

关键指标: 曝光时间与运动模糊的关系可以用一个简单公式估算:
运动模糊像素数 = 物体速度(pixel/s) × 曝光时间(s)
比如物体以 100 pixel/s 移动,曝光 1/30s,模糊就是 3.3 像素。超过 2 像素人眼就能察觉。

4.3 防抖与曝光时间

防抖技术说白了就是让你能用更长的曝光时间而不糊。但防抖不是万能的。

我曾经在一个手持夜景项目里踩过坑。当时觉得有 OIS(光学防抖)就放心了,把曝光时间拉到 1/4 秒。结果拍出来的照片边缘还是糊的。为什么?因为 OIS 只能补偿高频抖动,低频漂移它管不了。

防抖对曝光时间的增益大致如下:

防抖类型 安全快门增益 适用场景 局限性
无防抖 1×(等效焦距倒数) 三脚架、强光 手持超过 1/60s 容易糊
电子防抖(EIS) 1.5× ~ 2× 视频拍摄 有裁切,边缘画质下降
光学防抖(OIS) 2× ~ 4× 照片拍摄 低频漂移无效
OIS + EIS 融合 3× ~ 6× 旗舰手机 功耗高,发热明显
避坑指南: 我曾经在算法里直接信任 OIS 的增益系数,把曝光时间设到了 1/2 秒。结果用户反馈照片糊了一大片。后来加了陀螺仪数据校验,发现 OIS 在低光照下补偿能力会下降。所以防抖增益要动态调整,不能写死。

防抖和曝光时间的配合,我建议这样处理:

  • 静态场景: 优先用 OIS 增益,曝光时间可以拉到安全快门的 3~4 倍
  • 轻微运动: 限制在安全快门的 2 倍以内,配合 EIS 裁切
  • 强运动: 放弃防抖增益,直接用短曝光 + 高增益

4.4 运动模糊控制策略

运动模糊是曝光控制里最头疼的问题之一。你想想看,既要进光量够,又要画面不糊,这两个目标是矛盾的。

控制运动模糊,我常用的策略有四种:

  1. 曝光时间硬限制: 根据场景运动速度,直接限制最大曝光时间。比如检测到人脸,限制在 1/60s 以内。
  2. 自适应曝光分割: 把一帧分成多个短曝光子帧,然后对齐合成。这样等效进光量不变,但运动模糊减少了。
  3. 运动检测 + 区域差异化: 静止区域用长曝光,运动区域用短曝光。嗯,这个实现起来比较复杂,但效果最好。
  4. 卷帘快门补偿: 对于 CMOS 的卷帘快门效应,通过行曝光时间错位来补偿运动畸变。

这里重点说一下自适应曝光分割。我做过一个方案,效果还不错:

// 自适应曝光分割伪代码
function adaptiveExposureSplit(baseExposure, motionLevel) {
    // motionLevel: 0~1, 0表示静止, 1表示剧烈运动
    let splitCount = 1;
    if (motionLevel > 0.3) splitCount = 2;
    if (motionLevel > 0.6) splitCount = 4;
    if (motionLevel > 0.8) splitCount = 8;

    let subExposure = baseExposure / splitCount;
    let subFrames = captureSubFrames(subExposure, splitCount);

    // 对齐合成
    let alignedFrames = featureAlign(subFrames);
    let mergedFrame = mergeByWeight(alignedFrames, motionLevel);

    return mergedFrame;
}

这个方案的核心是:运动越剧烈,分割越细。但分割太多也有问题——子帧曝光太短,信噪比会下降。所以分割数量要跟增益配合着调。

我的经验: 分割数不要超过 8 帧。超过 8 帧后,对齐误差反而会引入新的模糊。而且处理时间也受不了,手机端 8 帧对齐大概要 15ms,再高就掉帧了。

最后说一个容易被忽略的点:运动模糊不只是物体运动造成的,还有相机自身的旋转。你想想看,手持拍摄时,相机绕光轴旋转产生的模糊,比平移模糊更明显。所以防抖算法里,旋转补偿的优先级应该高于平移补偿。

嗯,曝光时间控制这块内容不少,但核心就一句话:在保证不糊的前提下,尽量拉长曝光时间以提高信噪比。具体怎么平衡,就看你的场景和硬件能力了。