2. 图像传感器RAW数据采集与预处理
任务目标
本案例实现一个最小可复用的RAW数据采集与预处理流水线:从模拟传感器读取RAW图像,依次完成黑电平校正与镜头阴影校正,输出标准化后的图像数据,供后续ISP算法(如去马赛克、白平衡)使用。
核心实现
import numpy as np
class SensorRAW:
"""模拟传感器RAW数据采集"""
def __init__(self, width=640, height=480, bit_depth=10, black_level=64):
self.width = width
self.height = height
self.max_val = (1 << bit_depth) - 1 # 1023
self.black_level = black_level
# 模拟RAW数据:暗电流偏置 + 真实信号 + 噪声
np.random.seed(42)
# 模拟一个渐变场景(真实信号)
x = np.linspace(0, 1, width, dtype=np.float32)
y = np.linspace(0, 1, height, dtype=np.float32)
X, Y = np.meshgrid(x, y)
scene = 0.6 * X + 0.4 * Y # 0~1范围
# 生成RAW:黑电平 + 信号*动态范围 + 高斯噪声
raw = self.black_level + scene * (self.max_val - self.black_level)
raw += np.random.normal(0, 2, (height, width)) # 噪声
self.raw_data = np.clip(raw, 0, self.max_val).astype(np.uint16)
def read_raw(self):
"""返回原始RAW数据(模拟传感器输出)"""
return self.raw_data.copy()
class RAWPreprocessor:
"""RAW预处理:黑电平校正 + 镜头阴影校正"""
def __init__(self, black_level=64, max_val=1023):
self.black_level = black_level
self.max_val = max_val
def black_level_correction(self, raw):
"""减去黑电平并裁剪到有效范围"""
corrected = raw.astype(np.float32) - self.black_level
return np.clip(corrected, 0, self.max_val - self.black_level)
def lens_shading_correction(self, img, strength=0.3):
"""
镜头阴影校正:补偿边缘光强衰减
使用径向增益模型:中心增益1,边缘增益(1+strength)
"""
h, w = img.shape
cy, cx = h / 2, w / 2
y, x = np.mgrid[0:h, 0:w]
# 归一化半径(中心0,角落1)
r = np.sqrt(((x - cx) / cx) ** 2 + ((y - cy) / cy) ** 2)
r = np.clip(r, 0, 1)
# 增益曲线:中心1,边缘1+strength
gain = 1 + strength * r ** 2
corrected = img * gain
return np.clip(corrected, 0, self.max_val - self.black_level)
def preprocess(self, raw):
"""完整预处理流水线"""
# 1. 黑电平校正
img = self.black_level_correction(raw)
# 2. 镜头阴影校正
img = self.lens_shading_correction(img)
return img.astype(np.uint16)
# ===== 最小验证闭环 =====
if __name__ == "__main__":
# 1. 采集RAW数据
sensor = SensorRAW(width=640, height=480, bit_depth=10, black_level=64)
raw = sensor.read_raw()
print(f"RAW数据范围: [{raw.min()}, {raw.max()}]")
# 2. 预处理
preprocessor = RAWPreprocessor(black_level=64, max_val=1023)
processed = preprocessor.preprocess(raw)
# 3. 验证指标
# 3.1 黑电平校正后,暗区域均值应接近0
dark_region = raw[0:50, 0:50] # 图像左上角(场景值最低)
dark_processed = processed[0:50, 0:50]
print(f"暗区RAW均值: {dark_region.mean():.1f} → 校正后均值: {dark_processed.mean():.1f}")
# 3.2 镜头阴影校正:中心与边缘亮度差应缩小
center_val = processed[240-20:240+20, 320-20:320+20].mean()
corner_val = processed[0:40, 0:40].mean()
edge_ratio = corner_val / center_val
print(f"边缘/中心亮度比: {edge_ratio:.3f} (校正前应更低)")
# 3.3 数据范围有效性
print(f"处理后数据范围: [{processed.min()}, {processed.max()}]")
assert processed.min() >= 0, "存在负值"
assert processed.max() <= 959, "超出10bit有效范围"
print("✅ 预处理验证通过")
运行与验证
环境依赖:仅需Python 3.8+与NumPy(pip install numpy)。
运行方式:
python raw_preprocess.py
通过条件:
- 暗区均值从约64降至接近0,证明黑电平已去除;
- 边缘/中心亮度比大于0.85(校正前约0.7),证明镜头阴影得到补偿;
- 处理后数据范围在[0, 959]内,无溢出或负值。
输出中若三项指标均符合上述范围且断言通过,即表示预处理流水线工作正常,可为后续ISP模块提供标准输入。