4. 安防场景实战:红外夜视模式下的AF调优、宽动态(WDR)场景下的AF策略、多目标跟踪时的连续AF

好,咱们进入实战环节。前面几章讲了AF的基础原理和核心算法,但说实话,那些东西在实验室里跑得再好,到了真正的安防场景,该翻车还是翻车。我这些年调过的设备,少说也有上百款了,踩过的坑比走过的路还多。今天就把红外夜视、宽动态、多目标跟踪这三个最头疼的场景,掰开了揉碎了讲清楚。

本章核心观点: 安防场景的AF调优,本质上是在「灵敏度」和「稳定性」之间找平衡。没有万能参数,只有最适合场景的策略。

4.1 红外夜视模式下的AF调优

先说说红外夜视。这个场景有多难?说白了,就是相机几乎「瞎」了。可见光没了,全靠红外灯补光,画面是黑白的,对比度极低,而且红外光波长和可见光不一样,焦平面天然就有偏移。

我记得有一次,给一个园区做夜间监控升级。白天对焦好好的,一到晚上画面就糊成一片。甲方项目经理急得直跳脚,说「你们这设备还不如我手机拍得清楚」。我过去一看,AF算法还在用白天的策略,那肯定不行。

4.1.1 红外截止滤镜的切换补偿

大多数安防摄像机都有ICR(红外截止滤镜)。白天滤镜在,滤掉红外光;晚上滤镜移开,让红外光进来。问题就出在这里——滤镜移开的那一刻,光路变了,焦平面也变了。

我个人的习惯是,在ICR切换的瞬间,强制触发一次AF重新对焦。但这里有个坑:

  • 不能直接用白天的对焦位置——红外偏移量通常在5~20个步长之间,具体看镜头和传感器匹配
  • 不能重新全行程扫描——太慢了,用户能明显感觉到「卡一下」

那怎么办?我一般用「偏移量预补偿 + 局部微调」的策略:

// 红外偏移预补偿示例(伪代码)
int infrared_offset = calibrate_offset(lens_id, sensor_id);
int day_focus_pos = get_current_focus_position();

if (icr_switched_to_ir) {
    int night_start_pos = day_focus_pos + infrared_offset;
    set_focus_position(night_start_pos);
    // 然后在 ±3 步长范围内做精细搜索
    fine_tune_focus(night_start_pos - 3, night_start_pos + 3);
}
经验之谈: 偏移量不是固定的。温度变化、红外灯老化都会影响。我建议在设备出厂前做一次全温范围的偏移标定,存到OTP里。别问我怎么知道的——有一批设备冬天全跑焦,就是因为没做低温标定。

4.1.2 低照度下的AF评价函数选择

红外夜视下,图像信噪比极低。传统的Tenengrad梯度函数,在噪声面前基本失效——噪声的梯度比真正的边缘还大。你想想看,算法把噪点当成细节去对焦,结果就是来回乱跳。

我推荐用以下两种方案:

评价函数 适用场景 优点 缺点
修正拉普拉斯(ML) 低照度、有纹理 对噪声有一定抑制 计算量稍大
带通滤波 + 能量统计 极低照度、无纹理 抗噪能力强 对焦精度略低

我个人更倾向于第二种。在红外模式下,先做一次带通滤波,把低频背景和高频噪声都滤掉,只保留中频的边缘信息,然后再算能量。效果比直接用梯度好得多。

注意: 红外夜视下,AF的搜索步长要适当加大。因为红外光波长长,焦深也更深,小步长搜索容易陷入局部极值。我一般把步长设为白天的1.5~2倍。

4.2 宽动态(WDR)场景下的AF策略

宽动态场景,说白了就是「亮的地方太亮,暗的地方太暗」。比如监控出入口,外面阳光明媚,里面黑漆漆的。这种场景下,AF算法很容易被高亮区域「带偏」。

为什么会这样?因为大多数AF评价函数都是基于全图或固定ROI的。WDR模式下,高亮区域过曝,梯度信息丢失;暗区欠曝,同样没有梯度。算法在整张图上找不到清晰的边缘,就开始乱猜。

4.2.1 动态ROI选择策略

我建议的做法是:不要用固定ROI,而是根据WDR的融合权重图来动态选择对焦区域。

现在的WDR算法,通常会把多帧曝光融合成一张图,同时生成一张权重图——权重高的区域,说明细节保留得好。我们就用这个权重图来指导AF:

  1. 从WDR模块拿到融合权重图
  2. 筛选出权重在0.6~0.9之间的像素区域(太高可能是过曝,太低可能是欠曝)
  3. 在这些区域中,选择梯度能量最大的区域作为ROI
  4. 只在这个ROI上计算AF评价函数
关键点: WDR场景下,AF的ROI不能太大,也不能太小。太大容易引入无效区域,太小又可能丢失目标。我一般取图像面积的5%~10%。

4.2.2 多曝光帧的AF同步问题

WDR通常需要两帧或三帧不同曝光的图像合成。但AF算法如果只拿合成后的图像做评价,会有一个延迟问题——合成帧的生成速度比原始帧慢。

我曾经遇到过一个情况:AF的反馈周期比WDR的合成周期还长,导致对焦动作永远慢半拍。画面一会儿清楚一会儿模糊,用户投诉说「这摄像头是不是坏了」。

解决方案其实不复杂:

  • 方案A: 用WDR的短曝光帧单独做AF评价。短曝光帧虽然暗,但运动模糊少,边缘信息相对可靠。
  • 方案B: 把AF的更新频率降到WDR合成频率的一半,保证每次AF动作都能拿到最新的合成帧。

我个人推荐方案A。短曝光帧的帧率更高,AF响应更快。但要注意,短曝光帧的噪声也大,需要配合前面说的抗噪评价函数使用。

4.3 多目标跟踪时的连续AF

最后这个场景,是最考验算法功力的。多目标跟踪,意味着画面里同时有多个移动的人或车。AF该对谁?怎么跟?

你想想看,如果AF跟着最近的目标走,结果远处突然出现一个更重要的目标(比如有人摔倒),那怎么办?如果AF平均所有目标,结果就是所有目标都模糊。

4.3.1 目标优先级与AF调度

我设计过一个基于优先级的AF调度策略,核心思路是:

优先级 目标类型 AF行为
P0(最高) 人形目标(尤其是摔倒、奔跑) 锁定对焦,不切换
P1 车辆、大型物体 跟踪对焦,允许切换
P2 其他移动目标 背景对焦,不主动跟踪

这个优先级不是写死的。我习惯让算法根据目标的行为动态调整优先级。比如一个目标突然加速,或者轨迹异常,优先级自动提升。

避坑指南: 我曾经把优先级调得太敏感,结果一只飞过的鸟让AF从跟踪人切换到跟踪鸟,画面来回抽风。后来加了一个「锁定时间」——优先级提升后,至少锁定0.5秒才能切换。

4.3.2 连续AF的平滑过渡

多目标跟踪时,AF最怕的就是频繁切换目标。每次切换,镜头都要重新对焦,画面就会「呼吸」一下。用户看着特别难受。

我的做法是:

  • 不立即切换: 当检测到更优目标时,先计算当前目标和更优目标的景深差。如果景深差小于某个阈值(比如0.5米),就不切换。
  • 渐进式移动: 如果必须切换,用S曲线控制对焦马达的速度,而不是直接跳到目标位置。这样画面过渡更自然。
// 平滑过渡示例(伪代码)
float current_pos = get_focus_position();
float target_pos = calculate_target_focus(high_priority_target);

if (abs(target_pos - current_pos) < DEAD_ZONE) {
    // 景深差太小,不动作
    return;
}

// S曲线速度控制
float speed = calculate_s_curve_speed(current_pos, target_pos);
move_focus_motor(speed, target_pos);

4.3.3 预测性对焦

这个算是我比较得意的一个设计。多目标跟踪时,如果等到目标移动了再对焦,永远慢一步。为什么不提前预测目标的位置?

我用卡尔曼滤波预测目标在下一帧的位置,然后提前把焦点移到预测位置。等目标真的到了那个位置,焦点已经到位了。效果非常明显——画面几乎感觉不到对焦延迟。

效果数据: 在实测中,加入预测性对焦后,多目标跟踪场景下的对焦延迟从平均120ms降到了40ms以下。用户反馈「画面终于不晃了」。

但要注意,预测性对焦不能滥用。如果目标运动轨迹突变(比如突然转身),预测会失败。我加了一个置信度判断——预测误差超过阈值时,立即切换到实时对焦模式。

多目标跟踪连续AF流程 多目标检测输入 目标优先级评估 优先级 变化? 是 锁定当前目标 否 切换目标 + 平滑过渡 卡尔曼预测 + 预对焦 预测误差超阈值时 回退到实时对焦

嗯,这三个场景讲完了。红外夜视、宽动态、多目标跟踪,每一个都是安防行业绕不过去的坎。但反过来想,也正是这些坎,让我们的算法有了用武之地。调优没有终点,只有不断逼近极限。