3、Bayer域处理:Bayer Pattern格式、黑电平校正(BLC)、镜头阴影校正(LSC)、坏点校正(DPC)
各位好,欢迎来到第三章。前面我们聊了传感器和色彩基础,今天要进入真正的ISP处理流水线第一站——Bayer域。
为什么叫Bayer域?说白了,这时候图像数据还是“半成品”。每个像素只记录了红、绿、蓝中的一种颜色,像马赛克一样排列。我们所有后续处理,都得先在这个原始域里把底子打好。
我个人习惯把Bayer域处理比作“打地基”。地基不稳,后面调得再好也白搭。今天我们就来拆解这四个核心模块:Bayer格式、黑电平校正、镜头阴影校正、坏点校正。
3.1 Bayer Pattern格式:传感器的“方言”
先聊聊Bayer阵列。最常见的格式是RGGB,也就是一个2x2单元里,一个红、两个绿、一个蓝。人眼对绿色最敏感,所以绿色通道采样率翻倍。
但注意,不同传感器厂商的Bayer排列可能不一样。我遇到过几次坑:项目拿到一款新传感器,默认用RGGB去解,结果画面偏紫。查了半天,发现人家是BGGR排列。
| Bayer排列 | 第一行 | 第二行 | 常见传感器 |
|---|---|---|---|
| RGGB | R G R G ... | G B G B ... | Sony IMX系列 |
| BGGR | B G B G ... | G R G R ... | 部分OmniVision |
| GRBG | G R G R ... | B G B G ... | 部分三星传感器 |
| GBRG | G B G B ... | R G R G ... | 较少见 |
除了排列,还有位深。常见的是10bit、12bit、14bit。位深决定了动态范围的上限。我个人建议,能选12bit就别用10bit,后期调校空间大很多。
3.2 黑电平校正(BLC):把“零”找回来
黑电平校正,名字听着玄乎,其实道理很简单。传感器在完全无光的情况下,输出并不是0,而是一个偏置值,比如64(12bit下)。这个偏置就是黑电平。
为什么要校正?你想想看,如果黑电平是64,那么暗部细节就被抬高了,画面会发灰、发雾。更严重的是,它会影响后面的白平衡和色彩校正,导致偏色。
校正公式很简单:
// 伪代码示例
for each pixel:
corrected_pixel = raw_pixel - black_level
if corrected_pixel < 0:
corrected_pixel = 0
但实际项目中,黑电平不是固定值。它会随温度、增益、曝光时间变化。我做过一个项目,手机打游戏发热后,黑电平漂了4个LSB,暗部直接偏绿。
所以,成熟的ISP方案都会提供多组黑电平校正参数,按增益分段线性插值。调试时,建议至少标定3个增益点:低增益(1x)、中增益(4x)、高增益(16x)。
3.3 镜头阴影校正(LSC):拯救“暗角”
镜头阴影,也叫暗角或亮度衰减。镜头中心光线直射传感器,亮度高;边缘光线斜射,亮度低。再加上镜头本身的cos⁴衰减,边缘可能比中心暗30%-50%。
LSC的原理就是给边缘像素乘以一个大于1的增益,把亮度补回来。但这里有个陷阱——增益不能太大,否则噪声会被放大。
LSC参数通常以网格形式存储。比如把图像分成16x16的网格,每个网格顶点存一个增益值,中间区域双线性插值。
| 网格位置 | R通道增益 | Gr通道增益 | Gb通道增益 | B通道增益 |
|---|---|---|---|---|
| 中心 (8,8) | 1.00 | 1.00 | 1.00 | 1.00 |
| 左上角 (0,0) | 1.45 | 1.38 | 1.40 | 1.50 |
| 右下角 (15,15) | 1.42 | 1.36 | 1.38 | 1.48 |
我个人习惯,LSC校正后,边缘亮度要控制在中心亮度的95%以上。低于90%的话,边缘噪声会明显增加。如果镜头本身暗角太严重,建议先换镜头,别指望LSC硬拉。
3.4 坏点校正(DPC):消灭“星星”和“黑洞”
坏点,就是传感器上那些“不听话”的像素。有的永远亮着(亮点),有的永远黑着(暗点),还有的随机闪烁(噪点)。
坏点校正分两步:检测和替换。检测就是找出坏点,替换就是用周围正常像素的值把它填上。
检测方法主要有两种:
- 静态坏点检测: 出厂时标定,存一张坏点坐标表。优点是准,缺点是无法应对使用中产生的新坏点。
- 动态坏点检测: 实时判断。比如当前像素值比周围8个像素都高很多,就认为是亮点。优点是自适应,缺点是可能误判(比如拍星空)。
替换方法也有讲究:
// 中值替换示例(Bayer域)
// 假设当前坏点是R像素,取周围4个同色R像素的中值
uint16_t neighbors[4] = {pixel[-2][0], pixel[2][0], pixel[0][-2], pixel[0][2]};
// 排序取中值
uint16_t median = get_median(neighbors, 4);
corrected_pixel = median;
坏点校正的阈值设置很关键。阈值设得太低,好像素被误杀,画面变模糊;阈值设得太高,坏点漏检,画面出现“星星”。我一般建议,亮点阈值设为周围平均值的3-4倍,暗点阈值设为平均值的1/4-1/3。
3.5 知识体系总览
下面这张图,把Bayer域处理的四个模块串起来了。你可以看到,数据从传感器出来,先过BLC去掉偏置,再过LSC补偿亮度,最后DPC清理坏点。每一步都在为后面的Demosaic打基础。