图像传感器基础:CMOS 与 CCD 传感器、彩色滤波阵列(CFA)、Bayer 阵列详解
做去马赛克算法,第一件事不是调模型,而是搞懂图像传感器是怎么「看」颜色的。我早年踩过一个坑——直接用 RGB 三通道的数据训练网络,结果效果奇差。后来才发现,传感器压根没给我完整的 RGB,它只给了一个单通道的拜耳阵列。嗯,今天我们就从最底层开始,把这件事彻底讲清楚。
2.1 两种主流传感器:CCD 与 CMOS
先说说传感器本身。目前市面上主流的图像传感器就两种:CCD 和 CMOS。它们干的活一样——把光信号转成电信号,但实现方式完全不同。
| 对比维度 | CCD(电荷耦合器件) | CMOS(互补金属氧化物半导体) |
|---|---|---|
| 读出方式 | 逐行转移,统一输出 | 每个像素独立读出 |
| 功耗 | 较高(需要多组电压驱动) | 低(单电压供电) |
| 噪声 | 低(读出噪声小) | 较高(像素级放大器引入噪声) |
| 速度 | 较慢(串行读出) | 快(并行读出,支持高帧率) |
| 成本 | 高(工艺复杂) | 低(标准 CMOS 工艺) |
| 主流应用 | 科研、天文、高端工业 | 手机、相机、安防、自动驾驶 |
我个人习惯用 CMOS 传感器做项目。为什么?说白了,现在深度学习去马赛克面对的主要数据源就是手机和消费级相机,这些设备清一色全是 CMOS。CCD 虽然画质干净,但帧率低、功耗高,不适合实时处理。
2.2 彩色滤波阵列(CFA)——传感器为什么是「色盲」的?
你可能会问:传感器不是能感知颜色吗?其实单个像素只能感知光的强度,它分不清红绿蓝。那彩色照片怎么来的?答案是——在传感器表面盖一层彩色滤波阵列(CFA)。
每个像素上方只放一种颜色的滤光片,让这个像素只响应特定波段的光。这样一来,传感器输出的就是一张单通道的马赛克图像,每个位置只记录了 R、G、B 中的一种。
我曾经见过刚入行的同学直接把 RAW 数据当成灰度图丢进网络,结果训练出来的模型输出全是偏色的。嗯,这里要记住:RAW 数据虽然看起来像灰度图,但每个像素的「含义」不同——有的代表红色亮度,有的代表绿色亮度,有的代表蓝色亮度。
2.3 Bayer 阵列——最经典的 CFA 模式
CFA 有很多种排列方式,但最最常用的就是 Bayer 阵列。它由 Bryce Bayer 在 1976 年发明,到今天仍然是主流。
Bayer 阵列的排列规则很简单:
- 每 2×2 的像素块中,有 2 个绿色(G)、1 个红色(R)、1 个蓝色(B)
- 绿色占 50%,红色和蓝色各占 25%
- 排列方式有两种变体:RGGB 和 BGGR
为什么绿色多一倍?因为人眼对绿色最敏感,绿色通道携带了最多的亮度信息。你想想看,一张彩色图转成灰度图,绿色通道的权重本来就最高。
2.4 Bayer 阵列的数学表示
假设传感器分辨率为 H×W,那么 RAW 数据可以表示为:
# 以 RGGB 排列为例
# 坐标 (i, j) 处的像素值
# i 为行索引,j 为列索引
if i % 2 == 0: # 偶数行
if j % 2 == 0: # 偶数列 → 红色
pixel = R(i, j)
else: # 奇数列 → 绿色
pixel = G(i, j)
else: # 奇数行
if j % 2 == 0: # 偶数列 → 绿色
pixel = G(i, j)
else: # 奇数列 → 蓝色
pixel = B(i, j)
这个模式看起来简单,但实现去马赛克时,你必须精确知道每个像素的「颜色身份」。我习惯在代码里用一个 mask 矩阵来标记每个位置的颜色通道:
import numpy as np
def generate_bayer_mask(height, width, pattern='RGGB'):
"""生成 Bayer 掩码:0=R, 1=G, 2=B"""
mask = np.zeros((height, width), dtype=np.uint8)
if pattern == 'RGGB':
mask[0::2, 0::2] = 0 # R
mask[0::2, 1::2] = 1 # G
mask[1::2, 0::2] = 1 # G
mask[1::2, 1::2] = 2 # B
elif pattern == 'BGGR':
mask[0::2, 0::2] = 2 # B
mask[0::2, 1::2] = 1 # G
mask[1::2, 0::2] = 1 # G
mask[1::2, 1::2] = 0 # R
return mask
2.5 其他 CFA 模式简介
Bayer 虽然主流,但不是唯一。还有一些其他 CFA 模式,各有特点:
| CFA 类型 | 排列特点 | 优势 | 劣势 |
|---|---|---|---|
| Bayer (RGGB) | 2×2 块,G 占 50% | 简单、成熟、兼容性好 | 高频细节有伪色 |
| X-Trans (富士) | 6×6 块,不规则排列 | 减少摩尔纹 | 去马赛克算法复杂 |
| RGBW | 加入白色像素 (W) | 低光性能好 | 色彩还原难度大 |
| Quad Bayer | 4×4 块,4 个同色像素一组 | 支持高像素合并 | 分辨率损失 |
我个人建议初学者先死磕 Bayer。把 Bayer 上的去马赛克做透了,其他模式无非是换一个排列规则。我在项目中遇到过 X-Trans 的数据,当时直接把它重采样成 Bayer 格式再处理,省了很多麻烦。
2.6 本章知识结构图
下面这张图总结了图像传感器到去马赛克的核心流程:
2.7 避坑指南
最后分享几个我实际项目中踩过的坑:
- 不要忽略黑电平校正: RAW 数据通常有一个黑电平偏移(black level),不校正的话去马赛克结果会偏色。我习惯先减掉黑电平再归一化。
- 注意 Bayer 排列的起始位置: 不同相机可能从 (0,0) 开始是 R 或 B,写代码时一定要确认。我曾经因为这个原因,一个模型在 A 相机上效果很好,换到 B 相机直接崩了。
- 绿色通道的两种位置要区分: Bayer 阵列中 G 有两种位置——R 行和 B 行。有些去马赛克算法对这两种 G 分别处理,效果更好。
- 训练数据要模拟真实 CFA: 不要直接用 RGB 图像训练,一定要先模拟 CFA 采样过程,生成 RAW 数据再训练。否则模型没见过真实的马赛克模式,推理时效果会打折扣。