4. 去马赛克(Bayer插值)
任务目标
将单通道 Bayer RAW 数据插值成三通道 RGB 图像,实现双线性去马赛克算法,并验证输出图像边缘与细节的正确性。
实现方案
Bayer 格式中每个像素仅包含 R/G/B 中的一个分量,按 RGGB 模式排列。双线性插值利用邻域像素估计缺失的两个颜色分量:G 通道在 R/B 位置取上下左右均值,R/B 通道在 G 位置取对角或十字邻域均值。本案例提供完整可运行的 Python 实现,输入为模拟生成的 Bayer RAW 数组,输出为插值后的 RGB 图像。
完整代码
import numpy as np
def generate_bayer(rgb):
"""将 RGB 图像转换为 RGGB Bayer RAW 数组"""
h, w, _ = rgb.shape
bayer = np.zeros((h, w), dtype=np.float32)
bayer[0::2, 0::2] = rgb[0::2, 0::2, 0] # R
bayer[0::2, 1::2] = rgb[0::2, 1::2, 1] # G
bayer[1::2, 0::2] = rgb[1::2, 0::2, 1] # G
bayer[1::2, 1::2] = rgb[1::2, 1::2, 2] # B
return bayer
def demosaic_bilinear(bayer):
"""双线性 Bayer 插值,输入 HxW 单通道,输出 HxWx3 RGB"""
h, w = bayer.shape
rgb = np.zeros((h, w, 3), dtype=np.float32)
# 扩展边界(镜像)便于邻域计算
p = np.pad(bayer, 1, mode='reflect')
for y in range(h):
for x in range(w):
# 当前像素在扩展图中的坐标
py, px = y + 1, x + 1
# 判断当前像素类型(RGGB 模式)
if y % 2 == 0 and x % 2 == 0: # R 位置
R = p[py, px]
G = (p[py-1, px] + p[py+1, px] + p[py, px-1] + p[py, px+1]) / 4
B = (p[py-1, px-1] + p[py-1, px+1] + p[py+1, px-1] + p[py+1, px+1]) / 4
elif y % 2 == 0 and x % 2 == 1: # G 位置(R 行)
R = (p[py, px-1] + p[py, px+1]) / 2
G = p[py, px]
B = (p[py-1, px] + p[py+1, px]) / 2
elif y % 2 == 1 and x % 2 == 0: # G 位置(B 行)
R = (p[py-1, px] + p[py+1, px]) / 2
G = p[py, px]
B = (p[py, px-1] + p[py, px+1]) / 2
else: # B 位置
R = (p[py-1, px-1] + p[py-1, px+1] + p[py+1, px-1] + p[py+1, px+1]) / 4
G = (p[py-1, px] + p[py+1, px] + p[py, px-1] + p[py, px+1]) / 4
B = p[py, px]
rgb[y, x, 0] = R
rgb[y, x, 1] = G
rgb[y, x, 2] = B
return np.clip(rgb, 0, 255).astype(np.uint8)
# 最小验证示例
if __name__ == "__main__":
# 构造 4x4 测试图:左上红、右上绿、左下蓝、右下白
test = np.zeros((4, 4, 3), dtype=np.float32)
test[0:2, 0:2] = [255, 0, 0] # 红
test[0:2, 2:4] = [0, 255, 0] # 绿
test[2:4, 0:2] = [0, 0, 255] # 蓝
test[2:4, 2:4] = [255, 255, 255] # 白
bayer = generate_bayer(test)
result = demosaic_bilinear(bayer)
# 验证:中心区域颜色应接近原色
print("Bayer RAW:")
print(bayer)
print("\n插值结果 (中心 2x2):")
print(result[1:3, 1:3])
运行与验证
- 依赖:仅需
numpy,安装命令pip install numpy。 - 运行:将代码保存为
demosaic.py,执行python demosaic.py。 - 通过条件:观察输出结果——中心 2×2 区域中,位置 (1,1) 应接近红色 (255,0,0),(1,2) 接近绿色 (0,255,0),(2,1) 接近蓝色 (0,0,255),(2,2) 接近白色 (255,255,255)。由于双线性插值在色块边界会产生过渡,边缘像素值会有轻微偏差,但中心区域应保持正确色调。
关键说明
- 代码采用
reflect边界填充,避免边缘像素因邻域缺失而出现黑边。 - RGGB 模式中,偶数行偶数列为 R,奇数行奇数列为 B,其余为 G;插值公式严格对应此排列。
- 本实现为教学演示,未做伪影抑制(如 zipper 效应消除)。实际 ISP 中可替换为高级算法(如 AHD、VNG),但核心目标——从 Bayer 恢复 RGB——已完整实现。