第二章 RAW图与Bayer格式:Bayer Pattern详解、RAW图存储格式、黑电平与白平衡基础
各位同学好,我是你们的ISP调优讲师。今天咱们来聊聊ISP pipeline里最源头、也最容易被忽视的部分——RAW图和Bayer格式。
说实话,我见过不少工程师,算法调得飞起,但连sensor出来的RAW数据长什么样都没搞清楚。结果呢?调试时各种奇怪现象,查半天发现是Bayer排布搞反了,或者黑电平没扣对。嗯,这种坑我自己也踩过,所以今天咱们把地基打牢。
2.1 什么是Bayer Pattern?
先问一个问题:一个像素点,怎么同时感知红、绿、蓝三种颜色?
答案很简单——它做不到。单个像素只能感知光的强度,分不清颜色。那怎么办?
1976年,柯达的工程师Bryce Bayer想了个办法:在每个像素前面盖一个彩色滤光片,只让特定波长的光通过。然后把这些滤光片按一定规律排列,这就是Bayer Pattern。
核心思想:用牺牲分辨率的方式,换取彩色信息。每个像素只记录一种颜色,缺失的颜色靠周围像素插值得到。
典型的Bayer Pattern长这样:
G R G R G R
B G B G B G
G R G R G R
B G B G B G
你发现没?绿色像素占了总数的一半,红蓝各占四分之一。为什么?因为人眼对绿色最敏感。我当年第一次看到这个分布时,觉得Bayer真是个天才——用最少的资源,骗过了人眼。
2.2 常见的Bayer排列方式
实际项目中,Bayer排列不止一种。我列个表,大家对照着看:
| 排列名称 | 第一个像素 | 典型应用 |
|---|---|---|
| BGGR | 蓝 | Sony部分sensor |
| RGGB | 红 | OmniVision常用 |
| GRBG | 绿(左) | 三星部分sensor |
| GBRG | 绿(上) | 安森美部分sensor |
注意:我曾经在一个项目里,sensor datasheet写的是RGGB,但实际输出是BGGR。结果整幅图像偏色严重,查了三天才发现是Bayer顺序搞反了。所以拿到sensor后,第一件事就是拍一张纯色图,验证Bayer排列。
2.3 RAW图的存储格式
RAW图说白了,就是sensor直接输出的原始数据,没经过任何处理。它有几个关键参数:
- 位深:常见的有8bit、10bit、12bit、14bit。位深越高,动态范围越大。
- 存储方式:packed(紧凑)或unpacked(对齐)。
- 数据顺序:按Bayer排列逐行存储。
举个例子,一个10bit的RAW图,如果用unpacked方式,每个像素占2字节(16bit),高6位补0。如果用packed方式,5个像素占8字节,没有浪费。我个人的习惯是:调试阶段用unpacked,方便查看;量产阶段用packed,节省带宽。
下面是一个读取RAW图的伪代码:
// 假设sensor输出10bit RAW,BGGR排列,分辨率1920x1080
uint16_t raw_image[1080][1920];
for (int y = 0; y < 1080; y++) {
for (int x = 0; x < 1920; x++) {
// 根据Bayer排列,判断当前像素的颜色
if (y % 2 == 0 && x % 2 == 0) {
// B像素
} else if (y % 2 == 0 && x % 2 == 1) {
// G像素
} else if (y % 2 == 1 && x % 2 == 0) {
// G像素
} else {
// R像素
}
}
}
小技巧:调试时,我经常把RAW图直接保存成PGM格式(灰度图),用ImageJ打开。虽然看起来是灰蒙蒙的,但能直观看到Bayer pattern的纹理——如果看到棋盘格状的明暗变化,说明数据没问题。
2.4 黑电平(Black Level)
黑电平是什么?说白了,就是sensor在完全无光的情况下,输出的像素值。
理想情况下,没光应该输出0。但实际sensor有暗电流、有噪声,所以输出值不会是0。比如一个10bit的sensor,黑电平可能是64。这意味着:
- 像素值0~64之间,都是“黑”的
- 真正的有效信号,从64开始算起
黑电平校正的公式很简单:
corrected_pixel = raw_pixel - black_level
但要注意,不同sensor的黑电平可能不同,甚至同一颗sensor在不同增益下黑电平也会漂移。我遇到过最坑的一次,某款sensor在低增益下黑电平是64,高增益下变成了72。如果不做动态校正,暗部细节全丢了。
避坑指南:我曾经在调试一款安防摄像头时,发现夜间图像偏紫。查了三天,最后发现是黑电平没扣干净,导致暗部偏色。从那以后,我每次拿到新sensor,第一件事就是拍全黑图,统计黑电平的均值和标准差。
2.5 白平衡基础(AWB)
白平衡,说白了就是让白色物体在任何光源下都显示为白色。
为什么需要白平衡?因为不同光源的色温不同。日光灯偏蓝(色温高),白炽灯偏黄(色温低)。sensor本身没有“色温概念”,它只是忠实地记录每个像素的R、G、B值。如果不做校正,同一张白纸在不同光源下拍出来颜色完全不同。
白平衡的数学原理很简单:
R_out = R_in * R_gain
G_out = G_in * G_gain
B_out = B_in * B_gain
其中R_gain、G_gain、B_gain就是白平衡增益。通常以G通道为基准,所以G_gain=1.0,R_gain和B_gain根据光源调整。
举个例子,在日光灯下(色温约5000K),白平衡增益可能是:
R_gain = 1.2
G_gain = 1.0
B_gain = 1.5
为什么B_gain这么大?因为日光灯偏蓝,sensor的B通道响应强,需要压低B通道(或者说提升R和G来平衡)。
关键点:白平衡是在RAW域做的,还是在RGB域做的?答案是——都可以。但我的经验是:在RAW域做白平衡,效果更好,因为避免了插值带来的误差放大。
2.6 本章知识体系
为了让大家更直观地理解本章的知识结构,我画了一张图:
这张图把本章的核心知识点串起来了。你看,从Bayer Pattern出发,延伸到排列方式、存储格式,再到黑电平和白平衡——这些都是ISP pipeline最前端的处理环节。任何一个环节出问题,后面的算法再牛也救不回来。
我的建议:初学者不要急着调AWB、调去噪。先把RAW图读出来,看看Bayer排列对不对,黑电平扣没扣干净。这些基本功,决定了你后续调试的天花板。