3. 黑电平校正(BLC):原理、配置与工程经验
黑电平校正,英文叫 Black Level Correction,简称 BLC。这名字听起来挺唬人,其实说白了就一件事:把传感器在完全无光时不该有的那点信号给去掉。
你想想看,一个理想的图像传感器,在全黑环境下应该输出全 0。但现实世界哪有那么完美?由于半导体物理特性,即使你把镜头盖死,传感器依然会输出一个非零的底值。这个底值,就是黑电平。
如果不把它校正掉,你拍出来的黑色物体就会发灰,暗部细节被淹没,整个画面的对比度都会受影响。我早年刚接触 ISP 时,就吃过这个亏——有一款 sensor 的 BLC 没配好,拍出来的夜景全是灰蒙蒙一片,折腾了两天才找到根因。
3.1 BLC 的原理与作用
黑电平产生的根源,主要是两个:
- 暗电流:光电二极管在没有光照时,由于热激发产生的电子-空穴对。温度越高,暗电流越大。
- 读出电路偏移:像素的复位电压、源跟随器、列放大器等模拟电路,都会引入固定的直流偏移。
校正方法很简单——从每个像素的输出值中,减去一个参考值。这个参考值通常来自传感器边缘的 光屏蔽像素(Optical Black, OB),这些像素被金属层遮住,永远接收不到光。
核心公式:
P_out = P_raw - BLC_target
其中 BLC_target 通常取 OB 区域的平均值,或者由寄存器直接设定一个固定值。
BLC 的作用可以归纳为三点:
- 恢复黑电平基准:让全黑区域的输出接近 0,保证暗部纯净。
- 提升动态范围:如果不减掉底值,ADC 的量化范围就被白白浪费了一部分。
- 消除行间差异:不同行的读出电路偏移可能不同,BLC 可以逐行补偿。
3.2 高通平台 BLC 寄存器配置
在高通平台上,BLC 模块通常集成在 ISP 的前端(IFE 或 BPS 中)。配置的核心寄存器就那么几个,我直接给你列出来。
| 寄存器名称 | 作用 | 典型值 |
|---|---|---|
BLC_CFG |
使能 BLC 模块,选择校正模式 | 0x1(使能) |
BLC_TARGET |
设定目标黑电平值(单位:ADC code) | 64(10bit sensor) |
BLC_OB_AVG |
OB 像素平均值的读取结果 | 只读,由硬件自动计算 |
BLC_GAIN |
暗电流随温度变化的补偿增益 | 0x100(1.0x) |
BLC_OFFSET |
手动微调偏移量 | 0 |
配置流程大致如下:
- 读取 sensor 的 OB 区域平均值(通常由硬件自动统计)。
- 计算差值:
delta = OB_avg - BLC_TARGET。 - 将差值写入
BLC_OFFSET,或者让硬件自动补偿。 - 使能 BLC 模块,开始校正。
下面是一段典型的初始化代码片段:
// 高通平台 BLC 初始化示例
void blc_init(isp_hw_t *isp) {
uint32_t ob_avg;
// 1. 使能 BLC 模块
isp_reg_write(isp, BLC_CFG, 0x1);
// 2. 设定目标黑电平(10bit sensor 常用 64)
isp_reg_write(isp, BLC_TARGET, 64);
// 3. 读取 OB 平均值(硬件自动计算)
ob_avg = isp_reg_read(isp, BLC_OB_AVG);
// 4. 计算偏移并写入
int32_t delta = (int32_t)ob_avg - 64;
isp_reg_write(isp, BLC_OFFSET, delta & 0xFFF);
// 5. 设定增益补偿(默认 1.0x)
isp_reg_write(isp, BLC_GAIN, 0x100);
// 6. 启动校正
isp_reg_write(isp, BLC_CFG, 0x3); // bit0=使能, bit1=启动
}
小技巧: 不同 bit 深度的 sensor,BLC_TARGET 的取值不同。8bit 一般取 16,10bit 取 64,12bit 取 256。这个值不是拍脑袋定的,它对应 sensor 数据手册里推荐的黑电平偏移量。
3.3 暗电流补偿的工程经验
暗电流是 BLC 里最让人头疼的问题。它随温度变化,随曝光时间变化,甚至随 sensor 批次变化。如果你只做一次静态校正,那画面质量在高温下会急剧恶化。
我在一个手机项目中遇到过这种情况:夏天户外拍摄,手机发热后,暗部出现了明显的紫色条纹。查了半天,发现是暗电流补偿没跟上温度变化。
下面是我总结的几条工程经验:
- 动态补偿是必须的:不要指望一次校准管一辈子。建议每帧或每几帧重新读取 OB 区域,实时更新偏移量。
- 温度查表法:在产线标定时,记录不同温度下的暗电流值,做成 LUT。运行时根据 sensor 温度查表,插值得到补偿系数。
- 注意 OB 区域的行数:有些 sensor 的 OB 行只有几行,噪声较大。建议取多行平均,或者做中值滤波后再用。
- 小心过校正:如果 BLC 减得太多,暗部会变成负值,被 clamp 到 0 后反而丢失细节。我一般会留 1~2 个 code 的余量。
避坑指南: 我曾经在调试一款 4-cell sensor 时,发现 BLC 校正后画面出现横条纹。后来发现是 OB 区域和有效像素区域的读出时序不同,导致 OB 平均值不准。解决方案是改用 sensor 内部的「黑电平校准」模式,而不是自己算平均值。
另外,暗电流补偿还有一个容易被忽略的点——增益放大后的暗电流。当你把 ISP 的模拟增益或数字增益提高时,暗电流也会被同步放大。所以 BLC 必须在增益之前做,或者补偿值要乘以当前增益系数。
高通平台的做法是:BLC 模块放在增益模块之前,先减掉黑电平,再做增益。这样暗电流就不会被放大了。如果你自己写 pipeline,一定要注意这个顺序。
3.4 BLC 在 ISP Pipeline 中的位置
为了让你更直观地理解,我画了一张图,展示 BLC 在整个 ISP 前端的位置。
从图上可以清楚看到,BLC 是 Raw 域的第一个处理步骤。它的输出质量,直接决定了后面所有模块的输入基准。我见过不少工程师花大量时间调 AWB 和 CCM,结果发现是 BLC 没配好,白忙一场。
嗯,这里要注意一点:BLC 校正后的数据,可能会变成负值。硬件通常会对负值做 clamp 处理,但如果你在软件里做 BLC,一定要处理好符号位,否则会出现奇怪的 artifacts。
好了,关于黑电平校正,核心内容就是这些。原理不复杂,但工程实现上细节很多。记住一句话:BLC 是 ISP 的基石,基石不稳,上层全塌。