075、AI AWB实战:多光源混合场景下的色温估计与白平衡鲁棒性提升

发布时间:2026/7/18 15:06:42
075、AI AWB实战:多光源混合场景下的色温估计与白平衡鲁棒性提升 075、AI AWB实战多光源混合场景下的色温估计与白平衡鲁棒性提升一个让我失眠三天的案子去年夏天某旗舰机项目客户反馈在商场室内拍人像人脸总是偏黄。我拿到log一看AWB算出来的色温在4200K左右但实际场景是顶部暖色筒灯2800K加侧面玻璃幕墙透进来的日光5500K混合。传统AWB算法把两个光源平均了结果人脸肤色被拉向暖端衣服上的白色区域却偏蓝。更麻烦的是用户稍微转个角度色温就跳变300K视频里肉眼可见的闪烁。这个案子让我意识到多光源混合场景下的白平衡不是简单的“选一个色温”能解决的。今天这篇笔记就聊聊我们怎么用AI方法把这个坑填上。多光源混合为什么难搞传统AWB的核心假设是“场景中有一个主光源”然后通过统计色度空间上的分布找那个最可能的色温点。但混合场景下这个假设直接崩塌。举个例子一个场景里同时有白炽灯2000K和荧光灯4000K白色物体在两种光源下的响应完全不同。传统算法会看到色度图上出现两个聚类中心然后要么取平均结果两边都不对要么偏向其中一个另一个光源下的物体偏色。更麻烦的是不同光源的照度比例、物体表面的反射特性、甚至拍摄角度都会影响最终结果。我见过最离谱的案例是一个场景里同时有LED、卤素灯和日光传统算法直接输出一个“不存在”的色温值。AI AWB的基本思路我们团队的做法是把AWB从“单点估计”变成“多点估计融合”。具体来说用深度学习网络同时输出多个候选色温及其置信度然后根据场景语义做加权融合。网络结构上我们用了类似MobileNetV3的轻量级backbone输入是RAW域或简单预处理后的RGB图像注意这里强烈建议用RAW域因为Bayer格式保留了最完整的光谱信息别问我为什么踩过坑的人都知道。输出层设计成两个分支一个分支输出N个色温候选值我们用了5个另一个分支输出对应的置信度分数。训练数据是核心。我们收集了超过10万组多光源场景数据每个场景用分光辐射计测量实际光源分布然后人工标注“最佳白平衡参数”。这里有个技巧不要只标注一个色温值而是标注每个色温候选的权重。比如一个场景60%是日光、40%是白炽灯那标注就是两个色温值加权重。代码实现中的关键细节网络推理部分相对标准但后处理有几个容易翻车的地方。# 后处理多候选色温融合# 注意这里踩过坑直接加权平均会导致色温跳变defmulti_source_awb(raw_img,net_output):# net_output: [cct_candidates (5,), confidence (5,)]cct_candidatesnet_output[0]# 5个候选色温confidencenet_output[1]# 对应的置信度# 别这样写直接加权平均# final_cct np.sum(cct_candidates * confidence) / np.sum(confidence)# 这样会在两个候选色温之间平滑过渡但实际场景中光源切换是离散的# 正确做法先做置信度阈值筛选valid_maskconfidence0.3# 经验阈值根据场景调整ifnp.sum(valid_mask)0:# 兜底策略用最高置信度的候选final_cctcct_candidates[np.argmax(confidence)]else:# 对有效候选做加权但加入时间平滑# 这里用指数移动平均防止帧间跳变current_cctnp.sum(cct_candidates[valid_mask]*confidence[valid_mask])/np.sum(confidence[valid_mask])# 历史值缓存用全局变量或状态机维护final_cct0.7*current_cct0.3*prev_cct# 平滑系数可调另一个容易忽略的点是色温到RGB增益的转换。不同色温下R/G和B/G的映射关系是非线性的而且不同sensor的响应曲线不一样。我们维护了一个sensor-specific的查找表把色温值映射到具体的增益系数。# 色温到增益映射注意不同sensor差异很大# 这里用插值但别用线性插值要用样条插值defcct_to_gain(cct,sensor_idimx766):# 加载该sensor的标定数据calib_dataload_calibration(sensor_id)# calib_data包含多个色温点的R/G, B/G值# 用三次样条插值线性插值在高色温段误差很大fromscipy.interpolateimportCubicSpline cs_rCubicSpline(calib_data[cct],calib_data[r_gain])cs_bCubicSpline(calib_data[cct],calib_data[b_gain])r_gaincs_r(cct)b_gaincs_b(cct)# 注意g通道增益通常固定为1.0但有些sensor需要微调returnr_gain,1.0,b_gain训练数据的“脏活累活”数据采集是最痛苦的环节。我们搭建了一个多光源模拟环境用可调色温的LED面板模拟不同光源组合。每个场景拍摄时用分光辐射计记录实际光谱分布同时用色卡做参考。数据增强方面除了常规的亮度、噪声、旋转我们特别加了“光源比例扰动”。比如一个场景原本是60%日光40%白炽灯训练时随机调整到50%-70%范围让网络学会适应不同混合比例。还有一个trick在训练时加入“色温连续性损失”。因为真实场景中相邻帧的色温变化应该是平滑的所以我们把连续帧的色温输出也作为监督信号。这个在视频模式下的AWB效果提升非常明显。部署时的坑模型量化是第一个坑。我们用的MobileNetV3FP32推理没问题但量化到INT8后置信度输出变得不稳定有些场景下所有候选色温的置信度都低于0.3。后来发现是激活函数的量化精度不够把softmax的输出范围压缩得太小。解决方案是改用logits输出在后处理中再做softmax。第二个坑是推理延迟。在骁龙8 Gen2上模型推理大约需要8ms加上前后处理总共12ms。对于30fps的视频这个延迟可以接受但如果是60fps就需要优化。我们做了两件事一是把输入分辨率从全尺寸降到640x480二是用NNAPI加速。注意NNAPI的量化校准数据集要覆盖各种光源场景否则量化后精度会掉。实际效果与局限在商场、办公室、户外阴影等典型多光源场景下AI AWB的色温误差从传统算法的平均200K降到50K以内帧间色温跳变从150K降到20K。用户反馈的人脸偏色问题基本解决。但也不是万能的。极端场景下比如舞台灯光RGB三色激光混合AI模型也会翻车。因为训练数据里没有覆盖这种非连续光谱。另外在极低照度1 lux下RAW域的信噪比太低网络输出不稳定需要配合传统的灰度世界算法做融合。个人经验总结别迷信端到端纯端到端的AWB网络直接输出增益在混合场景下容易过拟合。多候选后处理融合的方式更鲁棒而且便于调试。数据比模型重要花80%的时间在数据采集和标注上20%的时间在模型设计上。我们试过各种SOTA网络结构最后发现MobileNetV3配合好的训练数据效果不比Transformer差。时间平滑是刚需单帧的AWB再准没有帧间平滑视频里就是闪烁。但平滑系数要动态调整场景变化快时减小平滑静止时增大平滑。保留传统算法的兜底AI模型总有没见过的场景。我们的方案里如果AI输出的置信度都低于阈值就回退到传统的灰度世界算法。这个阈值要经过大量场景测试我们最终定在0.25。调试工具链要跟上没有好的可视化工具调试AWB就是盲人摸象。我们开发了一个实时显示色温分布、候选色温、置信度、历史轨迹的工具定位问题快很多。最后说一句多光源AWB没有银弹。不同场景、不同sensor、不同用户偏好都需要针对性调优。AI给了我们更强的工具但最终效果还是靠工程师对场景的理解和耐心调试。