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 调优步骤,你可以直接拿去用。
- 准备全黑环境:盖上镜头盖,用遮光布包住镜头接口,确保无漏光。我习惯在暗室中操作,环境照度 < 0.01 Lux。
- 采集原始数据:设置传感器为默认增益(0dB),曝光时间 1/30s,输出 RAW 格式。采集至少 10 帧,取平均。
- 统计 OB 区域:读取传感器 OB 像素的平均值。如果传感器不支持 OB,则统计全图直方图,找到峰值位置。
- 计算校正值:校正值 = OB 平均值(或直方图峰值)。对于 12bit 数据,如果 OB 平均值为 64,则校正值设为 64。
- 验证校正效果:校正后,全黑画面的均值应接近 0,且直方图集中在 0 附近。如果还有偏移,微调校正值。
- 做增益/温度补偿:在不同增益(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 的整体脉络。我画图时习惯把“为什么做”放在最上面,然后是“怎么做”,最后是“怎么调好”。
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 | 三通道黑电平一致性 |