3. 黑电平校正 (BLC)

黑电平校正,简称 BLC。这名字听着挺学术,说白了就是告诉相机:「什么是真正的黑色」。

你想想看,传感器在完全没有光的情况下,输出的像素值并不是 0。因为电路本身有暗电流,ADC 也有偏置。如果不把这部分减掉,你拍出来的黑色物体就会发灰,暗部细节全被埋掉了。

我刚开始做 ISP 时,遇到过一台相机拍夜景,画面总是灰蒙蒙的。折腾了半天,最后发现就是 BLC 没校准好。嗯,从那以后我再也不敢小看这个模块了。

3.1 BLC 原理

BLC 的核心公式很简单:

P_out = max(P_in - BLC_offset, 0)

其中:

  • P_in:传感器原始输出值
  • BLC_offset:黑电平偏移量
  • P_out:校正后的像素值

但实际工程中,这个 offset 不是固定值。它跟很多因素有关:

  • 温度:暗电流随温度升高而增大,offset 会漂移
  • 增益:模拟增益放大时,黑电平也会被放大
  • 行位置:有些传感器不同行的暗电流不一致
  • 通道:R/Gr/Gb/B 四个通道的 offset 可能不同

关键认知:BLC 不是简单减一个常数。好的 BLC 模块会做「动态校正」,根据当前增益、温度、行位置查表或插值得到合适的 offset。

我见过一些方案,直接用固定值减。结果就是:低增益下暗部偏紫,高增益下暗部偏绿。说白了,这就是没处理好通道间的 offset 差异。

3.2 BLC 校准方法

校准 BLC,核心思路就是「拍一张全黑图,然后统计」。具体怎么做?我一般分三步:

3.2.1 采集黑帧

把镜头完全遮光,确保没有任何光线进入传感器。然后拍一张 raw 图。注意:

  • 环境温度要覆盖你产品的使用范围(比如 -20°C 到 60°C)
  • 增益要覆盖所有档位(低增益、中增益、高增益)
  • 曝光时间要覆盖典型值(长曝光时暗电流更明显)

注意:遮光不严是 BLC 校准最常见的坑。我曾经遇到过,校准出来的 offset 偏大,导致正常画面暗部被裁切。排查了两天才发现,是遮光罩漏光。

3.2.2 统计黑电平值

对黑帧的每个通道分别统计:

// 伪代码示例
for each channel (R, Gr, Gb, B):
    sum = 0
    count = 0
    for each pixel in channel:
        sum += pixel_value
        count++
    avg = sum / count
    offset[channel] = avg

但这里有个细节:传感器边缘的像素可能有光学暗区,统计时最好只取中间区域。我个人习惯取图像中心 80% 的区域。

3.2.3 建立 LUT 或拟合曲线

把不同温度、不同增益下的 offset 值整理成表:

温度 (°C) 增益 (dB) R offset Gr offset Gb offset B offset
-20 0 64 66 65 63
25 0 72 74 73 71
60 0 88 91 90 87
25 12 144 148 146 142

实际运行时,ISP 根据当前温度和增益查表,线性插值得到实时 offset。

工程技巧:如果传感器支持「光学黑像素 (OB pixels)」,可以利用这些像素实时计算 offset,省去查表。但 OB 像素的稳定性要验证,我遇到过 OB 像素本身有噪声的情况。

3.3 BLC 调试参数

调试 BLC 时,你主要跟这几个参数打交道:

  • global_offset:全局黑电平偏移,所有通道共用
  • channel_offset[4]:每个通道独立的偏移量
  • gain_compensation:增益补偿系数,offset 随增益变化的斜率
  • temperature_compensation:温度补偿系数,offset 随温度变化的斜率
  • row_noise_compensation:行噪声补偿,逐行调整 offset

调试流程我一般这样走:

  1. 先调全局 offset:在常温、0dB 增益下,让黑帧的均值接近目标值(通常是 64 或 128,取决于 ADC 位深)
  2. 再调通道平衡:确保 R/Gr/Gb/B 四个通道的黑电平一致,避免暗部偏色
  3. 然后调增益补偿:在不同增益下验证,offset 是否跟随增益线性变化
  4. 最后调温度补偿:在高低温环境下验证,offset 是否稳定

经验之谈:通道平衡是最容易被忽视的。很多工程师只调了全局 offset,结果暗部偏色严重。我建议在调试时,专门拍一张全黑图,放大到 400% 看每个通道的直方图,确保它们的均值相差不超过 1 个 DN。

3.4 效果验证

BLC 调得好不好,怎么验证?我一般用三个方法:

3.4.1 黑帧验证

拍全黑图,检查:

  • 均值是否接近目标值(比如 64)
  • 各通道均值差异是否 < 1 DN
  • 是否有行噪声或列噪声残留

3.4.2 暗部渐变验证

拍一张暗部有渐变的场景(比如黄昏的墙壁),检查:

  • 暗部是否偏色
  • 暗部细节是否被裁切(如果 offset 偏大,暗部会被裁成 0)
  • 从暗到亮的过渡是否平滑

3.4.3 全链路验证

把 BLC 放到整个 ISP 流水线中,看最终效果:

  • 暗部噪声是否被放大(BLC 减掉 offset 后,噪声相对比例会变大)
  • 暗部偏色是否在 AWB 后得到纠正
  • 动态范围是否受影响(BLC 裁切会导致暗部细节丢失)

避坑指南:我曾经遇到过,BLC 调完后黑帧看起来很好,但正常画面暗部发紫。后来发现是 BLC 和后面的数字增益模块配合有问题——数字增益把残留的通道差异放大了。所以,BLC 一定要和 AWB、CCM 联调。

3.5 BLC 知识体系

下面这张图,是我自己总结的 BLC 知识结构。你可以把它当作调试时的检查清单:

BLC 知识体系 黑电平校正 (BLC) 原理 暗电流 + ADC 偏置 P_out = max(P_in - offset, 0) 校准方法 采集黑帧 → 统计 → 建 LUT 温度/增益/通道独立统计 调试参数 global / channel / gain / temp 先全局 → 再通道 → 后补偿 效果验证 黑帧均值 / 通道差异 / 行噪声 暗部偏色 / 细节裁切 / 全链路 调试顺序建议 1. 常温 0dB 调全局 2. 调通道平衡 3. 调增益/温度补偿

这张图把 BLC 拆成了四个维度:原理、校准、调试、验证。你在实际项目中,可以按这个框架一步步来。别跳步,跳步容易踩坑。

好了,BLC 就聊到这儿。记住一句话:黑色不是天生的,是算出来的。把黑电平校准了,你的 ISP 流水线才算真正站稳了第一步。