1. 黑电平校正基础:物理机理与像素布局
各位同学,咱们今天正式开讲《黑电平校正与Gamma校正联合调优实战》的第一章。黑电平校正,听起来好像就是个减固定值的操作,对吧?其实不然。我做了这么多年图像调试,见过太多工程师把黑电平当成一个「死参数」来调,结果暗部偏色、噪点爆炸,怎么都救不回来。说白了,黑电平校正要是没搞明白,后面所有ISP模块都是在沙子上盖楼。
这一章,咱们先把根扎稳。我会从物理机理讲起,把暗电流、热噪声、OB像素这些概念串起来。你想想看,只有知道噪声从哪来,才知道怎么把它扣干净。
1.1 黑电平产生的物理机理
先问一个问题:为什么传感器在全黑环境下,输出值不是0?
理想情况下,没有光子入射,像素应该输出一个「数字0」。但现实是,你盖上镜头盖,读出数据一看——好家伙,几百甚至上千的DN(Digital Number)都有。这个非零的底数,就是黑电平(Black Level)。
它的来源主要有三个:
- 像素本身的暗电流:硅基半导体在无光照时,热激发产生的电子-空穴对,被势阱收集后形成信号。
- 读出电路偏移:列放大器、相关双采样(CDS)电路、ADC的直流偏置,都会引入固定偏移。
- 温度与曝光时间:暗电流随温度指数上升,曝光时间越长,积累的暗电荷越多。
核心公式(简化版):
Vout = Vphoto + Vdark + Voffset
其中 Vdark 是暗电流贡献,Voffset 是电路偏移。黑电平校正的目标,就是把 Vdark + Voffset 从输出中减掉。
我记得刚入行那会儿,调试一颗全局快门传感器,发现暗部一直偏紫。查了半天,发现是黑电平扣多了,把B通道的底噪扣成了负值,导致B通道被钳位到0,R/G通道还有残留。嗯,从那以后我养成了一个习惯:每次调黑电平,先看直方图,确认每个通道的底噪分布。
1.2 暗电流与热噪声
暗电流这东西,说白了就是「热出来的」。温度每升高6-8°C,暗电流翻一倍。你想想看,手机拍夜景,机身发热,暗电流蹭蹭往上涨。如果黑电平还是用常温标定值去扣,暗部肯定偏色。
暗电流的组成:
- 扩散暗电流:耗尽区边缘中性区热产生的少数载流子扩散到势阱。
- 耗尽区暗电流:耗尽区内热激发产生的电子-空穴对直接被收集。
- 表面暗电流:Si-SiO₂界面态引起的产生电流,与工艺质量强相关。
热噪声(暗电流散粒噪声)是暗电流的随机涨落。它的标准差等于暗电流电子数的平方根。举个例子:暗电流是100个电子,热噪声就是10个电子。这个噪声没法通过黑电平校正消除,只能靠后续的降噪模块处理。
| 参数 | 典型值(@25°C) | 温度系数 | 对黑电平的影响 |
|---|---|---|---|
| 暗电流密度 | 10-100 e⁻/pixel/s | 每6-8°C翻倍 | 随曝光时间线性增加 |
| 热噪声(散粒噪声) | √(暗电流电子数) | 随温度升高 | 不可校正,需降噪 |
| 读出电路偏移 | 50-200 DN | 弱温度依赖 | 固定偏移,可校正 |
实战小技巧:我个人习惯在传感器标定时,至少采集三个温度点(比如-10°C、25°C、60°C)的暗场数据。这样能拟合出暗电流的温度曲线,后续做温度补偿黑电平校正时,精度会高很多。
1.3 OB(Optical Black)像素布局与读取
好了,理论讲完了,咱们来看看实际芯片上怎么实现黑电平校正。几乎所有CMOS图像传感器都会在像素阵列周围布置一圈「光学黑像素」——OB像素。
OB像素的结构:
- 物理上被金属层遮挡,不接受光子。
- 电路连接与有效像素完全一致,包括复位、读出、放大。
- 因此,OB像素的输出 = 暗电流 + 读出偏移,正好是我们要扣掉的黑电平。
OB像素的布局,常见的有两种:
- 顶部/底部行布局:在像素阵列的顶部和底部各放几行OB像素。优点是面积小,缺点是离阵列中心远,温度梯度大时精度下降。
- 左右列布局:在阵列左右两侧放几列OB像素。优点是更接近有效像素的行位置,温度一致性更好。缺点是占用水平方向面积。
读取方式上,现代传感器通常支持两种模式:
- 每行读取:每读一行有效像素,同时读一行OB像素。实时性好,能跟踪行噪声。
- 帧前/帧后读取:在帧起始或结束集中读取OB像素。实现简单,但无法校正行噪声。
我曾经踩过的坑:有一次调试一颗高分辨率传感器,发现画面左侧偏暗、右侧偏亮。查了半天,发现OB像素只放在左侧,而传感器有轻微的行方向温度梯度。左侧OB测到的黑电平偏低,导致右侧有效像素扣多了。从那以后,我坚持要求传感器设计至少左右两侧都有OB像素,或者用软件做双边插值。
下面这张图,是我整理的黑电平校正知识体系。你可以把它当成这一章的「地图」:
1.4 黑电平校正的工程实现
了解了原理和布局,咱们看看实际代码里怎么处理。下面是一个简化的黑电平校正流程,用伪代码表示:
// 黑电平校正伪代码
// 输入:raw_image[H][W] (14-bit raw data)
// 输出:corrected_image[H][W]
// Step 1: 从OB像素区域计算黑电平
uint16_t ob_level = 0;
int ob_count = 0;
for (int row = 0; row < OB_ROWS; row++) {
for (int col = 0; col < W; col++) {
ob_level += raw_image[row][col];
ob_count++;
}
}
ob_level /= ob_count; // 平均黑电平
// Step 2: 逐像素减去黑电平,并钳位到0
for (int row = OB_ROWS; row < H; row++) {
for (int col = 0; col < W; col++) {
int32_t corrected = (int32_t)raw_image[row][col] - (int32_t)ob_level;
if (corrected < 0) corrected = 0;
corrected_image[row][col] = (uint16_t)corrected;
}
}
注意:实际工程中,我不会直接用单帧OB均值。我习惯用滑动窗口+中值滤波,剔除OB像素中的坏点和异常值。另外,对于高增益场景,黑电平会随增益放大,需要做增益补偿。这些细节,咱们在后面的章节会展开讲。
好了,第一章的内容就到这里。黑电平校正的物理机理、暗电流特性、OB布局,这三块是后续所有调优的基础。你把这些搞清楚了,后面讲Gamma校正联合调优时,才能理解为什么黑电平没扣干净,Gamma会把暗部噪声「拉」出来。