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

通过条件:

  1. 暗区均值从约64降至接近0,证明黑电平已去除;
  2. 边缘/中心亮度比大于0.85(校正前约0.7),证明镜头阴影得到补偿;
  3. 处理后数据范围在[0, 959]内,无溢出或负值。

输出中若三项指标均符合上述范围且断言通过,即表示预处理流水线工作正常,可为后续ISP模块提供标准输入。