3. 去马赛克算法:Bayer插值原理、经典插值算法与伪影抑制
各位同学,欢迎来到第三章。前面我们聊了传感器怎么把光变成电信号,但那个信号还是“黑白”的——每个像素只记录了红、绿、蓝其中一种颜色的强度。这就是Bayer阵列。今天我们要做的,就是从这种“残缺”的原始数据里,把每个像素缺失的另外两种颜色猜出来。这个过程,就叫去马赛克(Demosaicing)。
说白了,这就是ISP流水线上第一个真正考验算法功底的地方。做不好,后面所有模块都在给错误数据擦屁股。我当年刚入行时,就因为在插值上偷了个懒,结果整张图的边缘全是彩色锯齿,被前辈骂得狗血淋头。嗯,从那以后我再也不敢小看这一步了。
3.1 Bayer阵列:为什么是RGGB?
先看最经典的Bayer模式。人眼对绿色最敏感,所以绿色像素占了一半,红色和蓝色各占四分之一。常见的排列是RGGB:
| R | Gr | R | Gr |
|---|---|---|---|
| Gb | B | Gb | B |
| R | Gr | R | Gr |
| Gb | B | Gb | B |
注意,绿色通道其实分了两类:跟红色同行的Gr,跟蓝色同行的Gb。理论上它们应该一样,但实际传感器因为工艺差异,Gr和Gb之间会有固定偏差。我在调试某款国产传感器时就踩过这个坑——不校正Gr/Gb差异,整张图会有一道一道的横纹。
3.2 经典插值算法:从简单到复杂
3.2.1 双线性插值(Bilinear)
最朴素的想法:用周围同色像素的平均值来填补缺失值。比如要算一个红色像素位置的绿色值,就把上下左右四个绿色像素加起来除以4。
// 以R位置插值G为例
// 假设R在(2,2),周围G在(1,2)、(2,1)、(2,3)、(3,2)
G_at_R = (G[1][2] + G[2][1] + G[2][3] + G[3][2]) / 4
这个方法快,但问题也明显。它假设颜色变化是平滑的,遇到边缘就露馅了。我做过测试:用双线性插值处理一张有细条纹的测试图,结果边缘处出现了大量彩色伪影,就像给图像穿了一件花格子衬衫。
3.2.2 边缘导向插值(Edge-Directed)
既然双线性在边缘处翻车,那我们就先判断边缘方向,再沿着边缘方向插值。这就是边缘导向插值的核心思想。
具体做法:在待插值像素周围,分别计算水平方向和垂直方向的梯度。梯度小的方向就是边缘方向,我们就沿着那个方向取平均值。
// 在R位置插值G,先算梯度
// 水平梯度:|G[2][1] - G[2][3]|
// 垂直梯度:|G[1][2] - G[3][2]|
if (水平梯度 < 垂直梯度) {
// 水平边缘,用左右两个G平均
G_at_R = (G[2][1] + G[2][3]) / 2;
} else if (垂直梯度 < 水平梯度) {
// 垂直边缘,用上下两个G平均
G_at_R = (G[1][2] + G[3][2]) / 2;
} else {
// 平坦区域,用四个方向平均
G_at_R = (G[1][2] + G[2][1] + G[2][3] + G[3][2]) / 4;
}
这个改进效果很明显。边缘处的彩色伪影大幅减少,而且计算量只增加了一点点。我个人习惯在移动端ISP里用这个作为基线算法,性价比很高。
3.2.3 色差恒定理论(Constant Color Difference)
再深入一点。人眼对亮度变化敏感,对色度变化不敏感。所以我们可以利用一个假设:在局部区域内,颜色之间的差值(R-G, B-G)是近似恒定的。
基于这个理论,插值流程变成两步:
- 先用边缘导向法插出完整的G通道
- 利用色差恒定,从已知的R/G和B/G差值,反推出R和B的缺失值
这样做的好处是:R和B的插值结果会继承G通道的边缘信息,伪影更少。我见过很多工业相机ISP,核心算法就是色差恒定加上一些自适应改进。
3.3 伪影抑制策略:让图像更干净
不管用什么插值算法,伪影总是会以各种形式出现。下面是我在实际项目中总结的几种常见伪影和对应的抑制方法。
3.3.1 彩色摩尔纹(Color Moiré)
当图像中有高频纹理(比如布料、头发、远处的栅栏)时,插值算法容易产生不存在的彩色条纹。这是因为Bayer采样率不够,发生了混叠。
抑制方法:
- 低通滤波后插值: 先对Bayer数据做轻微的低通滤波,再插值。会损失一点细节,但摩尔纹基本消失。
- 自适应中值滤波: 在插值完成后,对色度通道做中值滤波,专门去除孤立的彩色噪点。
3.3.2 拉链效应(Zipper Effect)
在黑白交界的边缘,插值结果会出现一明一暗交替的像素,像拉链一样。这通常是因为梯度判断错误,导致插值方向选反了。
抑制方法:
- 多方向梯度融合: 不只用水平和垂直,加入45度和135度方向,取梯度最小的两个方向做加权平均。
- 后处理去拉链: 检测到拉链模式后,用周围像素的中值替换异常点。
3.3.3 伪彩色边缘(False Color)
在物体边缘,R、G、B三个通道的插值结果没有对齐,导致边缘出现红边或蓝边。这是去马赛克最头疼的问题之一。
抑制方法:
- 联合双边滤波: 以G通道为引导图,对R和B通道做联合双边滤波,强制R和B的边缘位置与G对齐。
- 色度约束: 限制R/G和B/G的比值在一个合理范围内,超出则向邻域值靠拢。
3.4 去马赛克流程总览
下面这张图展示了从Bayer原始数据到全彩色图像的完整流程。我把它画成了流程图,方便你理解各个模块的衔接关系。
3.5 实战中的权衡
最后聊点实际的。去马赛克算法没有银弹,你必须在以下几个维度做取舍:
| 算法 | 画质 | 计算量 | 内存占用 | 适用场景 |
|---|---|---|---|---|
| 双线性插值 | 低 | 极低 | 低 | 低端IPC、玩具摄像头 |
| 边缘导向插值 | 中 | 低 | 低 | 手机前置、行车记录仪 |
| 色差恒定+后处理 | 高 | 中 | 中 | 旗舰手机、微单相机 |
| 深度学习去马赛克 | 极高 | 高 | 高 | 专业相机、医疗影像 |
我个人建议:如果你在做AI芯片部署,优先考虑边缘导向插值+轻量后处理的组合。这个方案在画质和算力之间取得了很好的平衡,而且容易在NPU上做定点化加速。深度学习方案虽然画质好,但模型大小和推理延迟对边缘设备来说还是有点吃不消。