第二章 RAW域处理:黑电平校正、镜头阴影校正、坏点校正
各位同学,咱们今天聊聊RAW域的前三个关键处理。说白了,这是ISP管线的“地基”。地基没打好,后面再花哨的算法也白搭。
我个人习惯把RAW域处理比作“洗菜”。菜买回来,总得先摘掉烂叶子、洗掉泥巴、切掉根须吧?BLC、LSC、DPC干的就是这个活。它们处理的是传感器最原始的“生数据”,一步出错,步步出错。
2.1 黑电平校正(BLC)
先讲黑电平校正。为什么需要它?
你想想看,传感器在完全无光的情况下,输出值是不是应该是0?
不是的。实际上,由于传感器本身的暗电流、电路噪声等因素,即使在全黑环境,每个像素也会有一个微小的输出值。这个值就是“黑电平”。
BLC要做的,就是把这个底数减掉。公式很简单:
// 伪代码示例
// 假设黑电平值为64(12bit数据)
for each pixel in image:
pixel = pixel - black_level
if pixel < 0:
pixel = 0
嗯,这里要注意。黑电平值不是固定的。它会随温度、增益、曝光时间变化。我在项目中遇到过,冬天和夏天用同一套黑电平参数,结果夏天拍的夜景全是偏色的。后来才意识到,温度升高,暗电流增大,黑电平也跟着涨了。
所以,我建议在工程实现时,至少准备三组黑电平参数:低温、常温、高温。或者更狠一点,实时监测传感器温度,查表插值计算当前黑电平。
| 温度范围 | 黑电平偏移量(12bit) | 适用场景 |
|---|---|---|
| -20°C ~ 0°C | 60 | 冬季户外 |
| 0°C ~ 40°C | 64 | 日常室内 |
| 40°C ~ 60°C | 72 | 高温环境/长时间录像 |
2.2 镜头阴影校正(LSC)
接下来是镜头阴影校正。这个问题的根源在镜头本身。
任何镜头都有个物理特性:中心透光率高,边缘透光率低。拍出来的照片,中心亮、四周暗,这就是“阴影”或“暗角”。
为什么会这样?
两个原因。一是光学余弦四次方定律,边缘光线到达传感器的角度更大,能量衰减更厉害。二是镜头本身的机械结构会遮挡一部分边缘光线。
校正方法其实不复杂。预先拍一张均匀亮度的灰卡,记录下每个像素位置相对于中心的衰减比例。然后反过来乘回去就行。
// LSC校正示例
// gain_map 是预先标定的增益矩阵
for each pixel at position (x, y):
pixel = pixel * gain_map[x][y]
我个人习惯把LSC分成两步走。第一步是粗校正,用多项式拟合出一个平滑的增益曲面。第二步是细校正,用网格查表法补偿局部偏差。这样既保证了平滑性,又保证了精度。
另外,LSC的增益值不能太大。一般控制在4倍以内。如果边缘增益超过4倍,说明镜头设计本身就有问题,靠算法硬拉会引入大量噪声。
2.3 坏点校正(DPC)
最后是坏点校正。传感器制造过程中,难免会有几个像素点“坏掉”。
坏点分两种:
- 死点: 永远输出0或永远输出最大值,不随光照变化。
- 亮点: 输出值异常偏高,像一颗星星一样扎眼。
校正方法也分两类:静态校正和动态校正。
静态校正是在出厂时,把坏点的位置记录在一个表中。拍照时直接跳过这些点,用周围像素插值替代。
// 静态坏点校正
// bad_pixel_list 是出厂标定的坏点坐标列表
for each pixel at (x, y):
if (x, y) in bad_pixel_list:
pixel = interpolate_from_neighbors(x, y)
动态校正则是在运行时实时检测坏点。算法会判断当前像素是否明显偏离周围像素。如果是,就标记为坏点并校正。
动态校正的好处是能处理使用过程中新产生的坏点。但缺点是可能误判,比如把星空中的星星当成坏点给抹掉了。
我建议的做法是:静态校正打底,动态校正兜底。先用出厂标定的坏点表做一轮校正,再用动态检测算法捕捉新出现的坏点。动态检测的阈值要设得保守一些,宁可漏检,不可误检。
嗯,这三个处理做完,RAW数据才算“干净”了。接下来才能放心地去做去马赛克、白平衡、颜色校正等后续处理。
记住一句话:RAW域处理,慢就是快。前期多花点功夫把数据洗干净,后面能省十倍的时间。