黑电平校正(BLC):消除暗电流噪声,校准传感器的本底噪声

说实话,黑电平校正(Black Level Correction,BLC)是 ISP 流水线里最不起眼、但最容易翻车的一环。我见过不少团队,花大价钱调了 AWB、调了去噪,结果图像暗部发紫、偏绿,查来查去,最后发现是 BLC 没做对。

说白了,BLC 就是告诉芯片:「在没有光的时候,你应该输出 0。」但现实是,传感器在暗场下也会读出一些信号——这就是暗电流噪声。如果不把它减掉,整幅图像就像垫了一层灰雾,暗部细节全被淹没了。

核心一句话:BLC 的目标是让传感器在全黑环境下的输出值归零,消除像素阵列的本底噪声。

暗电流噪声是怎么来的?

每个像素本质上是一个光电二极管加一个浮置扩散区。即使没有光子入射,热激发产生的电子也会被收集,形成暗电流。温度每升高 6-8°C,暗电流大约翻一倍。嗯,这就是为什么手机拍夜景久了,画面会越来越「脏」。

我在项目中遇到过一款 1/1.7 英寸的传感器,常温下暗电流只有 5-8 LSB,但到了 60°C 环境测试时,暗电流飙到了 40 LSB 以上。如果不做动态 BLC,整张图就像蒙了一层灰纱。

BLC 的两种主流实现方式

方式 原理 优点 缺点
OB(Optical Black)行/列校正 利用传感器边缘被遮挡的像素(OB 像素)计算暗电平 实时跟踪温度变化,无需额外校准 OB 像素数量有限,统计噪声较大
全局固定校正 出厂时标定一个固定偏移值,每帧减去该值 实现简单,计算量小 无法适应温度变化,暗部容易偏色

我个人习惯优先用 OB 校正。为什么?因为温度一变,暗电流就变,固定值根本扛不住。你想想看,手机在冬天户外和夏天口袋里的温度差个 20°C 很正常,固定 BLC 在这种场景下基本是摆设。

OB 校正的工程实现

大多数 CMOS 传感器会在像素阵列的顶部和底部预留几行被金属遮挡的像素,这些就是 OB 像素。ISP 会读取这些像素的平均值,作为当前帧的黑电平基准。

代码实现大致是这样的:

// 假设 sensor 输出 10-bit RAW,OB 像素位于前 4 行
uint16_t ob_sum = 0;
int ob_count = 0;

for (int row = 0; row < OB_ROWS; row++) {
    for (int col = 0; col < SENSOR_WIDTH; col++) {
        ob_sum += raw_buffer[row][col];
        ob_count++;
    }
}

uint16_t ob_avg = ob_sum / ob_count;

// 对每个像素做减法,并 clamp 到 [0, 1023]
for (int row = OB_ROWS; row < SENSOR_HEIGHT; row++) {
    for (int col = 0; col < SENSOR_WIDTH; col++) {
        int corrected = raw_buffer[row][col] - ob_avg;
        raw_buffer[row][col] = (corrected < 0) ? 0 : (corrected > 1023 ? 1023 : corrected);
    }
}
小技巧:OB 像素本身也有噪声,直接用单行均值容易引入行噪声。我建议对多行 OB 做中值滤波后再取平均,能有效剔除坏像素的干扰。

BLC 调优的三大坑

调 BLC 看起来简单,不就是减个值吗?但实际踩坑的人不少。我列几个常见的:

  • OB 像素被污染:有些传感器的 OB 区域靠近边缘,镜头暗角或杂散光会照进去,导致 OB 值偏高,校正过度。我曾经遇到一款模组,贴膜后 OB 值涨了 10 个 LSB,暗部直接变黑死。
  • BLC 与数字增益的顺序:如果先做 BLC 再做数字增益,暗电流噪声会被放大。正确的做法是:BLC → 去噪 → 数字增益。这个顺序我吃过亏,调了三天才发现是流水线顺序反了。
  • BLC 后的负值处理:减法后可能出现负值,直接 clamp 到 0 会丢失暗部细节。我建议保留 1-2 bit 的负值余量,或者用线性映射把负值区域平滑过渡到 0。
注意:BLC 不是减得越多越好。过度校正会导致暗部细节丢失,图像看起来「死黑」。判断标准很简单:盖上镜头盖,输出图像应该是纯黑(0,0,0),而不是偏紫或偏绿。

BLC 在 ISP 流水线中的位置

下面这张图展示了 BLC 在整个 ISP 流程中的位置。你会发现,它几乎是 RAW 域的第一个处理模块——因为后面的所有模块都依赖一个「干净」的底噪基准。

ISP 流水线中 BLC 的位置 Sensor RAW BLC 去噪 数字增益 后续模块 关键说明: • BLC 必须在去噪之前执行,否则暗电流噪声会被去噪模块误认为是有效信号。 • 数字增益放在 BLC 和去噪之后,避免放大暗电流噪声。 • 如果传感器支持多帧 OB 统计,建议做帧间平滑,防止单帧 OB 抖动导致闪烁。

实战中的 BLC 参数调优

调 BLC 时,我一般会准备三组测试条件:

  1. 暗场(镜头盖全黑):检查输出是否接近 0,R/G/B 通道是否平衡。如果偏色,说明 BLC 没校准到位。
  2. 低照度灰卡(1-10 lux):观察暗部是否有色偏或条纹。这个场景最容易暴露 BLC 与去噪的配合问题。
  3. 高温暗场(60°C 恒温箱):验证 OB 校正能否跟上暗电流的变化。如果不行,就得考虑温度补偿曲线。

我曾经在一个安防项目中,发现高温下图像暗部出现紫色条纹。排查了两天,最后发现是 OB 像素的读出路径和有效像素不一致,导致 OB 值偏低了 3 个 LSB。补上这个偏移后,问题就解决了。嗯,这种硬件差异,光看 datasheet 是看不出来的,必须实测。

BLC 的进阶:自适应与温度补偿

对于高端安防或车载应用,单纯的 OB 校正还不够。我建议引入温度传感器,建立暗电流-温度曲线,做自适应补偿。

大致思路是:

  • 在产线标定阶段,记录不同温度下的 OB 值,拟合出一条二次曲线。
  • 运行时,读取板载温度传感器,查表得到当前温度下的理论暗电流。
  • 用理论值对 OB 统计值做加权修正,提高稳定性。

这样做的好处是,即使 OB 像素被污染或损坏,系统仍然能给出合理的黑电平基准。

我的经验:温度补偿曲线建议用 3 个温度点标定(-20°C、25°C、60°C),二次拟合就够了。点太多反而过拟合,实际效果并不好。

总结一下 BLC 的调优要点

检查项 合格标准 常见问题
暗场输出 R/G/B 三通道均值 < 1 LSB 偏色、死黑、灰雾
OB 像素稳定性 帧间波动 < 2 LSB 闪烁、行噪声
温度适应性 -20°C ~ 60°C 暗场输出 < 3 LSB 高温偏紫、低温偏绿
与去噪的配合 低照度下无条纹、无伪色 暗部条纹、色斑

BLC 调好了,后面的 AWB、CCM 才能站得稳。别小看这一步,它是整个 ISP 流水线的地基。地基歪了,上面盖多漂亮的楼都没用。