2. 黑电平校正(BLC):原理与作用、校正方法、实战调优技巧

黑电平校正,英文叫 Black Level Correction,简称 BLC。很多刚入行的工程师觉得这步很简单,不就是减个值嘛。嗯,确实原理不复杂,但实际调起来,坑可不少。

我个人的理解是:BLC 是图像质量的“地基”。地基没打平,后面做再好的 AWB、CCM,出来的颜色都是歪的。你想想看,如果黑色都不纯,那红色能正吗?

核心一句话:BLC 的目标是让传感器在完全无光(全黑)条件下,输出的数字信号为 0。

2.1 为什么需要黑电平校正?

传感器本身有暗电流。即使没有光,像素也会产生少量电荷。这个“本底噪声”会被 ADC 转换成数字值,导致全黑画面看起来发灰、发绿。

我在项目中遇到过一款低照度传感器,默认黑电平偏移量高达 64 LSB(12bit 数据)。如果不校正,夜间画面整体偏绿,而且暗区细节完全被噪声淹没了。

BLC 要解决三个问题:

  • 消除固定模式噪声:传感器各像素的暗电流不一致,导致画面有固定的竖条纹或网格。
  • 恢复黑电平基准:确保 0 Lux 时输出为 0,为后续的 Gamma、CCM 提供正确的黑点参考。
  • 提升动态范围:校正后,暗部信号被“压缩”到有效范围,亮部细节才能保留。

注意:BLC 不是简单的“减一个固定值”。不同增益、不同温度下,黑电平偏移量是变化的。我曾经见过有人用固定值校正,结果温度一升高,画面直接偏色——这就是没做温度补偿的后果。

2.2 黑电平校正的两种主流方法

实际工程中,BLC 分两大类:硬件校正和软件校正。我建议你优先用硬件校正,实在没办法再用软件补。

校正方式 原理 优点 缺点
硬件校正(OB 像素) 传感器边缘有被遮挡的像素(Optical Black),用它们的平均值作为黑电平参考 实时、准确、不占用 ISP 资源 需要传感器支持 OB 区域;OB 像素数量有限,统计噪声较大
软件校正(统计法) 在全黑环境下采集一帧图像,统计直方图,找到黑电平偏移量 灵活,可做温度/增益补偿 需要额外标定;环境必须全黑,否则会误判

2.3 实战调优流程

下面是我在项目中总结的一套 BLC 调优步骤,你可以直接拿去用。

  1. 准备全黑环境:盖上镜头盖,用遮光布包住镜头接口,确保无漏光。我习惯在暗室中操作,环境照度 < 0.01 Lux。
  2. 采集原始数据:设置传感器为默认增益(0dB),曝光时间 1/30s,输出 RAW 格式。采集至少 10 帧,取平均。
  3. 统计 OB 区域:读取传感器 OB 像素的平均值。如果传感器不支持 OB,则统计全图直方图,找到峰值位置。
  4. 计算校正值:校正值 = OB 平均值(或直方图峰值)。对于 12bit 数据,如果 OB 平均值为 64,则校正值设为 64。
  5. 验证校正效果:校正后,全黑画面的均值应接近 0,且直方图集中在 0 附近。如果还有偏移,微调校正值。
  6. 做增益/温度补偿:在不同增益(0dB、6dB、12dB、18dB、24dB)和不同温度(-20°C、25°C、60°C)下重复步骤 2-5,建立补偿表。

我的小技巧:做增益补偿时,不要用线性拟合。我试过,高增益段偏差很大。建议用分段线性或查表法,精度更高。

2.4 代码示例:BLC 校正实现

下面是一个简化的 BLC 校正代码,用 C 风格实现,方便你移植到 ISP 固件中。

// BLC 校正函数
// input: 原始 RAW 数据
// output: 校正后 RAW 数据
// blc_offset: 黑电平偏移量(由标定获得)
// bit_depth: 传感器位深(如 10, 12, 14)
void blc_correction(uint16_t *raw_data, uint32_t pixel_count, 
                    uint16_t blc_offset, uint8_t bit_depth) {
    uint16_t max_val = (1 << bit_depth) - 1;
    
    for (uint32_t i = 0; i < pixel_count; i++) {
        // 减去黑电平偏移
        int32_t corrected = (int32_t)raw_data[i] - (int32_t)blc_offset;
        
        // 钳位到有效范围
        if (corrected < 0) {
            corrected = 0;
        } else if (corrected > max_val) {
            corrected = max_val;
        }
        
        raw_data[i] = (uint16_t)corrected;
    }
}

// 增益补偿示例:根据当前增益查表
uint16_t get_blc_offset_with_gain(uint8_t gain_index) {
    // 标定数据:增益索引 0-5 对应的 BLC 偏移量
    static const uint16_t blc_table[6] = {64, 68, 76, 92, 120, 160};
    if (gain_index > 5) gain_index = 5;
    return blc_table[gain_index];
}

2.5 BLC 知识体系图

下面这张图帮你理清 BLC 的整体脉络。我画图时习惯把“为什么做”放在最上面,然后是“怎么做”,最后是“怎么调好”。

黑电平校正(BLC)知识体系 为什么需要 BLC? 暗电流导致黑电平偏移 全黑画面发灰/发绿 固定模式噪声 竖条纹/网格噪声 影响后续模块 AWB/CCM/Gamma 偏差 BLC 校正方法 硬件校正(OB 像素) 实时准确,依赖传感器支持 软件校正(统计法) 灵活,需全黑环境标定 实战调优技巧 增益补偿 分段线性/查表法 温度补偿 -20°C ~ 60°C 标定 验证方法 直方图 + 均值检查 核心原则:BLC 是图像质量的“地基”,必须优先做好 地基不平,上层建筑全歪

2.6 常见问题与避坑指南

调了这么多年 BLC,我踩过的坑不少。下面几个问题你大概率也会遇到。

  • 问题:校正后暗部偏紫/偏绿
    原因:BLC 校正值不准确,导致 R/G/B 通道的黑电平不一致。我曾经遇到过一款传感器,G 通道的暗电流比 R/B 通道大 10 LSB,用统一值校正后暗部偏绿。解决办法:分通道标定 BLC 偏移量。
  • 问题:高增益下画面闪烁
    原因:BLC 校正值随增益变化,但补偿表不够精细。我建议在 0dB~30dB 范围内至少取 6 个点做标定,高增益段加密。
  • 问题:温度升高后画面偏色
    原因:没有做温度补偿。传感器温度每升高 10°C,暗电流大约翻倍。我习惯在产线标定时加入温度传感器,建立温度-偏移量查找表。

曾经踩过的坑:有一次我为了省事,直接用固定值做 BLC,结果客户反馈夜间监控画面偏绿。排查了两天才发现是温度变化导致黑电平漂移了 20 LSB。从那以后,我所有项目都强制要求做温度补偿。

2.7 调优效果评估指标

调完 BLC 后,怎么判断效果好不好?我一般看三个指标。

指标 理想值 测量方法
全黑画面均值 0 ~ 2 LSB 盖上镜头盖,采集 10 帧取平均
全黑画面标准差 < 4 LSB 反映噪声水平,越小越好
R/G/B 通道均值差 < 1 LSB 三通道黑电平一致性