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 黑电平校正核心逻辑 Sensor RAW 数据输入 BLC 模式选择 静态 BLC 固定偏移值 动态 BLC OB 像素统计 + 自适应 通道独立补偿 校正后 RAW 数据 BLC 位于 ISP Pipeline 最前端,直接影响后续 AWB、CCM 模块

这张图展示了 BLC 在 ISP Pipeline 中的位置和两种配置路径。静态 BLC 走左边,动态 BLC 走右边。我个人建议,除非你的产品环境温度非常稳定(比如实验室仪器),否则一定要上动态 BLC。

最后说一句:BLC 调好了,画面干净通透;调不好,后面所有模块都在给 BLC 擦屁股。嗯,就是这么重要。


公众号:蓝海资料掘金营,微信 deep3321