3. 黑电平校正(BLC):从暗电流到硬件流水线
黑电平校正,圈内人常叫 BLC。这步处理看着简单,但坑特别多。我最早做 sensor 驱动时,觉得 BLC 不就是减个固定值嘛,后来被暗角偏色问题折腾了两周,才老老实实把这块吃透。
说白了,BLC 要解决一个根本问题:传感器在没有光照时,输出值不是零。这个非零的底数,就是黑电平。如果不扣掉它,后面做白平衡、Gamma 都会出偏差,暗部尤其明显。
3.1 黑电平是怎么来的?
原因主要有三个,我列个表方便对照:
| 成因 | 物理机制 | 典型量级(12bit) |
|---|---|---|
| 暗电流 | 硅基热激发产生的电子-空穴对,温度每升高 6-8°C 翻一倍 | 32-128 DN |
| 像素复位噪声 | FD 节点复位后残留的 kTC 噪声,与电容和温度相关 | 8-24 DN |
| 读出电路偏移 | 列放大器、CDS 电路的直流偏置不一致 | 4-16 DN(列间差异) |
你想想看,暗电流是温度的函数。手机在冬天拍和夏天拍,黑电平能差出 3-4 倍。我遇到过一款安防相机,白天户外 60°C 时黑电平飙到 180 DN,用固定值减 64 直接废了暗部细节。
3.2 全局 BLC vs 局部 BLC
先讲最简单的方案——全局 BLC。整帧图像减同一个值,或者乘同一个增益。实现简单,硬件一个减法器搞定。但问题也很明显:
- 传感器边缘像素暗电流通常比中心高(因为温度分布不均)
- 列读出电路偏移是逐列不同的
- Bayer 模式中 R/Gr/Gb/B 四个通道的暗电流特性不一样
所以实际项目中,局部 BLC 才是主流。我把它分成三个层级:
| 层级 | 粒度 | 校正方式 | 硬件开销 |
|---|---|---|---|
| 通道级 | R/Gr/Gb/B 各一个值 | 四通道独立减法 | 低 |
| 列级 | 每列一个偏移值 | 查表 + 减法 | 中 |
| 像素级 | 每个像素独立校正 | LUT 或多项式 | 高 |
我个人习惯,消费级产品用通道级就够了,工业相机或天文摄影才上像素级。别一上来就堆硬件,先看看 sensor 数据手册里黑电平的 row-wise 分布曲线,再决定。
3.3 动态黑电平校正算法
固定值 BLC 在温度变化时就是灾难。动态校正的核心思路:从图像中实时估算当前黑电平。
主流做法是利用 光屏蔽像素(Optical Black, OB)。传感器边缘有一圈被金属遮挡的像素,它们永远收不到光,输出就是纯黑电平。算法流程如下:
- 从 RAW 数据中提取 OB 区域(通常是每行的前 4-16 列)
- 对 OB 像素做中值滤波,剔除坏点和随机噪声
- 按通道分别计算 OB 均值(R/Gr/Gb/B 分开)
- 用滑动窗口对帧间结果做平滑,防止跳变
- 将估算值应用到有效像素区域
关键参数:
- OB 行数:通常取 4-8 行,太少噪声大,太多浪费带宽
- 平滑系数 α:0.1-0.3,帧率越高 α 可以越大
- 更新阈值:帧间变化超过 2 DN 才更新,避免微抖
我曾经在一个项目中遇到 OB 区域被镜头渐晕污染的情况——镜头边缘遮光不够,OB 像素漏光了。结果动态 BLC 把黑电平估得越来越低,画面整体偏亮。后来加了 OB 有效性检测,如果 OB 均值高于预期阈值,就回退到上一帧的值。
3.4 硬件实现方案
讲真,BLC 的硬件实现是 ISP 流水线里最直观的模块之一。我画个架构图帮你理解:
硬件实现时,有几个细节值得注意:
- OB 行缓存:至少缓存 4 行 OB 数据,才能做中值滤波。用 line buffer 实现,面积不大
- 减法器位宽:输入 12bit,黑电平最大 256,输出保持 12bit。注意处理下溢——减成负数要钳位到 0
- 流水线级数:OB 统计和像素校正可以并行。统计模块提前 4 行算出当前帧的黑电平,校正模块跟上
- 寄存器配置:平滑系数、更新阈值、OB 起始位置都做成可配,方便调试
我的经验:调试 BLC 时,先关掉所有其他 ISP 模块,拍一张全黑图(盖上镜头盖)。看直方图,理想情况是集中在 0-4 DN。如果看到明显的列条纹,说明列级 BLC 没做好。如果整体偏左或偏右,调 OB 均值偏移量。
3.5 避坑指南
最后分享几个我踩过的坑:
- OB 区域被污染:镜头遮光不好、sensor 封装漏光,OB 值不准。解决方案是加 OB 有效性检测,或者用暗场校准帧替代实时 OB
- 温度突变:手机从空调房拿到室外,黑电平在几秒内漂移 20-30 DN。平滑系数要自适应,温度变化大时加快更新速度
- Bayer 通道不平衡:Gr 和 Gb 通道的黑电平可能差 4-8 DN,如果不分开处理,绿色通道会出现网格噪声。一定要四通道独立统计
- 高增益下的噪声放大:BLC 减掉的底数被后续增益放大,暗部噪声会变明显。可以考虑在 BLC 之后做一级降噪,或者用分段校正