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
调试流程我一般这样走:
- 先调全局 offset:在常温、0dB 增益下,让黑帧的均值接近目标值(通常是 64 或 128,取决于 ADC 位深)
- 再调通道平衡:确保 R/Gr/Gb/B 四个通道的黑电平一致,避免暗部偏色
- 然后调增益补偿:在不同增益下验证,offset 是否跟随增益线性变化
- 最后调温度补偿:在高低温环境下验证,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 就聊到这儿。记住一句话:黑色不是天生的,是算出来的。把黑电平校准了,你的 ISP 流水线才算真正站稳了第一步。