3、黑电平校正 (BLC):BLC 原理、暗电流补偿、动态 BLC 与静态 BLC 配置
黑电平校正,圈里人常叫 BLC。这玩意儿看着简单,但坑不少。我刚开始调 ISP 时,觉得 BLC 不就是减个固定值嘛,后来发现根本不是这么回事。
说白了,BLC 要解决的是「黑色不黑」的问题。你想想看,一个全黑的场景,Sensor 理论上应该输出 0,但实际不是。因为有暗电流、有热噪声,Sensor 会输出一个非零值。这个值如果不扣掉,整个画面就会发灰、发雾。
3.1 暗电流补偿:为什么黑色不黑?
暗电流是 Sensor 的物理特性。光电二极管在没有光照时,由于热激发也会产生电子。温度越高,暗电流越大。我曾在项目中遇到过夏天户外监控画面偏紫的问题,查了半天,最后发现是 BLC 没跟上温度变化。
暗电流补偿的核心公式很简单:
// 伪代码:BLC 校正
for each pixel (x, y):
corrected_pixel = raw_pixel - black_level(x, y)
if corrected_pixel < 0:
corrected_pixel = 0
但这里有个关键点:black_level 不是全局常数。不同像素位置的暗电流不一样,甚至 R、G、B 通道的暗电流也不一样。我习惯的做法是,先采集全黑帧,然后统计每个通道的均值。
核心要点:暗电流补偿必须考虑温度、增益、曝光时间三个因素。温度每升高 6-8°C,暗电流大约翻一倍。
3.2 静态 BLC 配置:简单但有限
静态 BLC 就是固定减一个值。很多 Sensor 厂商会在 datasheet 里给出推荐值,比如 R 通道减 64,Gr 通道减 66,Gb 通道减 65,B 通道减 68。
配置方式通常是通过 I2C 写寄存器:
// 静态 BLC 配置示例(RKISP 驱动)
// 设置 R 通道黑电平偏移
rkisp_blc_config->channel_r = 64;
// 设置 Gr 通道黑电平偏移
rkisp_blc_config->channel_gr = 66;
// 设置 Gb 通道黑电平偏移
rkisp_blc_config->channel_gb = 65;
// 设置 B 通道黑电平偏移
rkisp_blc_config->channel_b = 68;
静态 BLC 的优点是简单、稳定。但缺点也很明显——它不随环境变化。你想想看,白天 25°C 和晚上 45°C 的暗电流能一样吗?肯定不一样。所以静态 BLC 只适合环境温度变化不大的场景。
注意:静态 BLC 配置时,不要直接使用 Sensor 默认值。我建议至少做一次全黑帧标定,确认实际暗电流值。曾经有个项目,直接用了 datasheet 的值,结果暗部偏色严重,折腾了两周才发现是 BLC 没标定。
3.3 动态 BLC:自适应才是王道
动态 BLC 说白了就是让黑电平值跟着环境跑。它会实时统计图像中的暗区像素,动态调整补偿值。
实现思路一般有两种:
- 基于全黑行(OB,Optical Black):Sensor 边缘有被遮挡的像素,这些像素理论上接收不到光,它们的输出就是当前暗电流。动态 BLC 会实时统计这些 OB 像素的均值。
- 基于图像统计:从图像中找出最暗的区域(比如镜头盖、暗角),假设这些区域应该是黑色,然后反推暗电流。
我个人更推荐 OB 方案,因为它不依赖场景内容。RKISP 的 Pipeline 里,BLC 模块通常放在最前面,紧跟着 Sensor 数据输入:
// 动态 BLC 流程(简化版)
1. 读取 OB 区域像素(通常每行前 16-32 个像素)
2. 计算 OB 均值,排除异常像素(坏点)
3. 根据增益和温度查表修正
4. 对每个通道分别计算补偿值
5. 应用到全图
经验之谈:动态 BLC 的更新频率不要太高。我一般设成每 30 帧更新一次,或者每 0.5 秒更新一次。更新太快反而会引起画面闪烁,尤其是场景中有大面积暗区时。
3.4 BLC 与后续模块的联动
BLC 不是孤立存在的。它会影响后面的 AWB(自动白平衡)和 CCM(色彩校正矩阵)。
举个例子:如果 BLC 没扣干净,暗部残留了偏红的暗电流,AWB 统计时会把暗部像素也算进去,导致整个画面的白平衡偏蓝。这就是为什么有时候你调 AWB 调了半天没用,回头一看是 BLC 的问题。
| BLC 问题 | 表现 | 影响范围 |
|---|---|---|
| 补偿不足 | 暗部发灰、发雾 | 整体对比度下降 |
| 补偿过度 | 暗部细节丢失、偏色 | 暗部信噪比恶化 |
| 通道不平衡 | 暗部偏色(常见偏紫) | AWB 异常、CCM 失效 |
| 更新频率过快 | 画面闪烁 | 用户体验差 |
3.5 实战中的避坑指南
我曾经在一个安防项目中踩过一个大坑。Sensor 在低增益下 BLC 表现正常,但切换到高增益(比如 30dB 以上)时,暗电流非线性增长,静态 BLC 完全跟不上。画面暗部直接变成紫色。
后来怎么解决的?我加了一个增益相关的补偿表:
// 增益-暗电流补偿表(示例)
// 增益(dB) : 补偿值偏移
0 : 0
10 : 2
20 : 5
30 : 12
40 : 28
50 : 60
嗯,这里要注意:这个表需要针对每颗 Sensor 单独标定。不同批次、不同工艺的 Sensor,暗电流特性都有差异。
总结一下我的经验:
- 静态 BLC 只适合实验室环境或温度稳定的场景
- 动态 BLC 必须做,但更新策略要保守
- BLC 标定不能只看全黑帧,还要看不同增益、不同温度下的表现
- BLC 出问题,先查暗部偏色,再查 AWB 异常
这张图展示了 BLC 在 ISP Pipeline 中的位置和两种配置路径。静态 BLC 走左边,动态 BLC 走右边。我个人建议,除非你的产品环境温度非常稳定(比如实验室仪器),否则一定要上动态 BLC。
最后说一句:BLC 调好了,画面干净通透;调不好,后面所有模块都在给 BLC 擦屁股。嗯,就是这么重要。
公众号:蓝海资料掘金营,微信 deep3321