3. 黑电平校正(BLC)

3.1 黑电平到底是什么?

说白了,黑电平就是传感器在「完全没光」的情况下,输出的信号值。

理想情况下,没光就应该输出0。但现实不是这样。传感器本身有暗电流,像素电路有偏置,ADC也有偏移。所以即使你把镜头盖死,读出来的数据也不是0,而是一个固定的基底值。

这个基底值,我们就叫它黑电平。

我刚开始做ISP时,遇到过一台相机拍出来的黑色物体发灰。折腾了半天,最后发现是黑电平没扣干净。嗯,从那以后我再也不敢小看这个参数了。

核心理解: 黑电平校正 = 从原始数据中减去一个「暗场基底」,让黑色真正回到0附近。

3.2 黑电平校正的作用

校正黑电平,主要有三个目的:

  • 恢复黑色纯度 — 让暗部不发灰、不发紫
  • 保证动态范围 — 如果黑电平太高,暗部细节会被吃掉
  • 为后续模块打基础 — 白平衡、去马赛克、Gamma校正都依赖正确的黑电平

你想想看,如果黑电平没扣准,后面的AWB算出来的增益就是错的。一步错,步步错。

3.3 黑电平的校准方法

校准方法分两种:硬件校准 和 软件校准。

校准方式 原理 适用场景 精度
硬件校准 传感器内部自动扣除OB(Optical Black)像素 大部分手机、安防摄像头 中等
软件校准 采集暗场数据,软件计算偏移量并扣除 工业相机、医疗影像、高端监控 高

我个人习惯用软件校准,尤其是做项目落地时。硬件校准虽然方便,但不同温度、不同增益下黑电平会漂。软件校准可以动态补偿。

3.3.1 软件校准的步骤

  1. 采集暗场数据 — 盖上镜头盖,设置目标增益和曝光时间
  2. 计算均值 — 对每个通道(R/Gr/Gb/B)分别计算像素均值
  3. 确定偏移量 — 均值就是该通道的黑电平值
  4. 写入参数 — 将偏移量写入ISP寄存器或配置文件

这里有个坑:不同温度下黑电平不一样。我曾经在夏天调试一款户外摄像头,白天校准好的参数,晚上温度降了10度,画面暗部直接偏绿。后来我加了温度查表补偿,才搞定。

经验值参考: 常见8-bit传感器黑电平在16~64之间,10-bit传感器在64~256之间。如果偏差太大,先检查硬件电路。

3.4 BLC参数调试实战

调试BLC参数,我一般分三步走:

3.4.1 第一步:确认暗场数据

先把镜头盖死,拍一张全黑图。然后看直方图。

// 伪代码:读取暗场数据
uint16_t dark_frame[HEIGHT][WIDTH];
sensor_capture_raw(dark_frame);

// 分通道统计
uint32_t sum_r = 0, sum_gr = 0, sum_gb = 0, sum_b = 0;
int count_r = 0, count_gr = 0, count_gb = 0, count_b = 0;

for (int y = 0; y < HEIGHT; y++) {
    for (int x = 0; x < WIDTH; x++) {
        switch (bayer_pattern(x, y)) {
            case R: sum_r += dark_frame[y][x]; count_r++; break;
            case GR: sum_gr += dark_frame[y][x]; count_gr++; break;
            case GB: sum_gb += dark_frame[y][x]; count_gb++; break;
            case B: sum_b += dark_frame[y][x]; count_b++; break;
        }
    }
}

float blc_r = (float)sum_r / count_r;
float blc_gr = (float)sum_gr / count_gr;
float blc_gb = (float)sum_gb / count_gb;
float blc_b = (float)sum_b / count_b;

打印出来看看。如果四个通道的均值差异超过5个DN(数字码值),说明传感器本身有通道不平衡。这时候不能只用一个全局黑电平,必须分通道校正。

3.4.2 第二步:设置BLC参数

大多数ISP芯片支持两种模式:

  • 全局模式 — 所有像素减去同一个值
  • 分通道模式 — R/Gr/Gb/B各自独立减去不同值

我建议优先用分通道模式。原因很简单:Gr和Gb的差异是很多暗部偏色的根源。

// 寄存器配置示例(分通道模式)
isp_write_reg(BLC_CTRL, 0x01);          // 启用分通道BLC
isp_write_reg(BLC_R, (uint16_t)blc_r);
isp_write_reg(BLC_GR, (uint16_t)blc_gr);
isp_write_reg(BLC_GB, (uint16_t)blc_gb);
isp_write_reg(BLC_B, (uint16_t)blc_b);

3.4.3 第三步:验证效果

设置完参数后,再拍一张暗场图。看直方图峰值是否在0附近。然后拍一张正常亮度的灰卡图,看暗部是否偏色。

注意: 黑电平扣多了会丢失暗部细节,扣少了暗部发灰。理想状态是:暗场直方图峰值在0~2之间,且不出现大量负值。

3.5 BLC与温度、增益的关系

黑电平不是固定不变的。它随两个因素变化:

  • 温度 — 温度每升高10度,暗电流大约翻倍
  • 模拟增益 — 增益放大后,黑电平也被放大了

所以做产品时,我一般会建一个二维查表:

增益 \ 温度 -10°C 0°C 25°C 50°C
1x 12 16 24 40
2x 24 32 48 80
4x 48 64 96 160

这个表需要在实验室标定。标定一次,后面量产直接用。

3.6 BLC知识体系总览

下面这张图把BLC的核心逻辑串起来了:

黑电平校正(BLC)知识体系 黑电平校正 BLC 原理与作用 校准方法 参数调试 暗电流补偿 恢复黑色纯度 硬件校准(OB) 软件校准(暗场) 分通道校正 温度增益补偿 输出:干净的黑场 + 准确的暗部 为AWB、去马赛克、Gamma提供正确基底 ⚠️ 避坑提醒 不要只校准一次就量产。温度变化、增益变化都会导致黑电平漂移。 建议在产线做多温度点标定,建立增益-温度补偿表。

3.7 常见问题与排查思路

调试BLC时,我遇到过不少坑。这里列几个典型的:

  • 暗部偏绿/偏紫 — 大概率是Gr和Gb通道的黑电平不一致。分通道校正即可解决。
  • 暗部出现条纹噪声 — 可能是OB像素区域被污染,或者硬件校准没关干净。检查寄存器配置。
  • 画面整体偏亮/偏暗 — 黑电平扣多了或扣少了。重新采集暗场数据。
  • 温度变化后偏色 — 黑电平随温度漂移了。加温度补偿表。
调试小技巧: 在ISP调试工具里,把BLC临时设为0,拍一张暗场图。这时候看到的「不该有的亮度」就是黑电平的真实值。这个方法比看寄存器值更直观。

嗯,BLC这部分就讲到这里。记住一句话:黑电平是ISP的基石,基石不稳,上层全白搭。