4. 黑电平校正(BLC):BLC的作用、Offset校准方法、温度对BLC的影响

黑电平校正,圈里人常叫它BLC。这玩意儿看着不起眼,但你要是没处理好,整张图就废了。我刚开始调ISP那会儿,就吃过这个亏——画面暗部发紫,怎么调都调不回来,折腾了两天才发现是BLC的offset没设对。

说白了,BLC要解决什么问题?你想想看,传感器在完全无光的情况下,理论上应该输出0。但现实是,它总会输出一个非零的值。这个值就是黑电平。如果不把它减掉,暗部就会偏色,动态范围也会被压缩。

核心一句话:BLC就是找到传感器在“全黑”状态下的输出值,然后在每个像素上把它减掉。

4.1 BLC到底在干什么?

我习惯把BLC理解成“归零操作”。传感器每个像素都有暗电流,温度越高,暗电流越大。这个暗电流叠加在真实信号上,就像你称东西时秤没归零一样。

BLC的作用主要有三个:

  • 消除暗电流偏移:把全黑条件下的输出拉回到0附近
  • 保证暗部色彩准确:R、G、B三个通道的黑电平如果不一致,暗部就会偏色
  • 释放动态范围:黑电平占用了ADC的码值,减掉后能多用几个bit

嗯,这里要注意一点。BLC不是简单减一个固定值。不同像素、不同增益、不同温度下,黑电平都不一样。所以校准是个细致活。

4.2 Offset校准方法——我常用的两种方式

Offset校准,说白了就是找到那个“减多少”的值。方法有很多,我挑两个最实用的讲。

方法一:OB像素校准法

现在的传感器都会留几行或几列被遮挡的像素,叫Optical Black(OB)区域。这些像素收不到光,它们的输出就是纯黑电平。

具体做法:

  1. 读取OB区域所有像素的值
  2. 计算平均值(或者中位数,看噪声情况)
  3. 用这个值作为当前帧的BLC offset
// 伪代码示例:OB像素校准
uint16_t blc_offset = 0;
uint32_t sum = 0;
int ob_pixel_count = 0;

for (int row = 0; row < OB_ROWS; row++) {
    for (int col = 0; col < OB_COLS; col++) {
        // 跳过坏像素
        if (!is_defect_pixel(row, col)) {
            sum += ob_buffer[row][col];
            ob_pixel_count++;
        }
    }
}

blc_offset = sum / ob_pixel_count;

// 对每个有效像素做校正
for (int i = 0; i < TOTAL_PIXELS; i++) {
    pixel_out[i] = (pixel_in[i] > blc_offset) ? 
                   (pixel_in[i] - blc_offset) : 0;
}

我的经验:OB像素数量别太少,至少64个以上,不然噪声太大。我曾经在一个项目里只用了16个OB像素,结果每帧的offset都在跳,画面闪烁。后来改成128个,稳得很。

方法二:暗场校准法

有些场景下OB区域不可靠,或者你想做更精细的校准。那就拍一张全黑图——盖上镜头盖,在完全无光的环境下拍一帧。

步骤:

  • 盖上镜头盖,设置目标增益和曝光时间
  • 采集一帧或多帧图像
  • 对每个像素(或每个通道)计算平均值
  • 把这个值存成LUT,运行时查表校正

这个方法精度高,但麻烦。因为不同增益、不同曝光时间下黑电平不一样,你得拍很多组数据。

注意:暗场校准对环境要求极高。哪怕有一丝漏光,校准结果就废了。我建议在暗室做,用黑色绒布把镜头裹严实。

4.3 温度对BLC的影响——这个坑我踩过

温度对BLC的影响有多大?我直接说数据吧。

温度范围 黑电平偏移量(12bit ADC) 影响程度
-20°C ~ 0°C +2 ~ +5 LSB 轻微
0°C ~ 40°C +5 ~ +15 LSB 中等
40°C ~ 85°C +15 ~ +50 LSB 严重

你看,温度从25°C升到60°C,黑电平可能漂了20多个LSB。如果不做补偿,暗部直接偏绿或偏紫。

为什么会这样?因为暗电流随温度呈指数增长。传感器内部的热激发电子多了,黑电平自然就上去了。

我遇到过最头疼的一个案子:车载摄像头,夏天暴晒后车内温度能到70°C。BLC如果不做温度补偿,画面暗部全是噪点,颜色也偏得离谱。后来我们加了温度传感器,做了个简单的线性补偿模型:

// 温度补偿BLC示例
float temperature_coeff = 0.8;  // 单位:LSB/°C
int reference_temp = 25;        // 校准时的温度

int current_temp = read_temperature_sensor();
int temp_delta = current_temp - reference_temp;

uint16_t compensated_offset = blc_offset + 
                             (int)(temp_delta * temperature_coeff);

// 用补偿后的offset做校正
for (int i = 0; i < TOTAL_PIXELS; i++) {
    pixel_out[i] = (pixel_in[i] > compensated_offset) ? 
                   (pixel_in[i] - compensated_offset) : 0;
}

避坑指南:温度系数不是线性的!高温区斜率更大。我建议分段线性拟合,或者直接用查表法。精度要求高的场景,可以考虑用多项式拟合。

4.4 知识体系总览

下面这张图是我自己整理的BLC知识结构,你看一眼就能明白整个逻辑。

黑电平校正(BLC)知识体系 BLC核心目标 消除暗电流偏移 保证暗部色彩准确 释放动态范围 校准方法一:OB像素校准 校准方法二:暗场校准 温度对BLC的影响(关键!) 方案:线性补偿模型 方案:分段/查表补偿

这张图把BLC的三大作用、两种校准方法、以及温度影响和补偿方案串起来了。你调试的时候,按这个思路走,基本不会漏掉关键点。

最后说一句:BLC调好了,暗部细节就出来了。调不好,后面做再多AWB、CCM都是白搭。我见过太多人一上来就调颜色,结果暗部偏色怎么都救不回来——其实就是BLC没做对。


可可精品资料库