1. 相机传感器原始数据读取与格式转换

相机传感器原始数据读取与格式转换 学习卡片

任务目标

本案例实现从工业相机传感器读取RAW Bayer数据,完成黑电平校正、坏点校正、白平衡、去马赛克及色彩空间转换,最终输出标准BGR图像,为后续ISP处理链路提供输入。

环境依赖

Python 3.8+,OpenCV 4.5+,NumPy。RAW数据文件为10bit packed格式,分辨率1920×1080,Bayer模式为RGGB。

核心实现

import numpy as np
import cv2

# ---------- RAW数据读取与解析 ----------
def read_raw10_packed(filepath, width=1920, height=1080):
    """读取10bit packed RAW数据(每5字节存4像素)"""
    raw_size = width * height * 5 // 4
    with open(filepath, 'rb') as f:
        data = np.fromfile(f, dtype=np.uint8, count=raw_size)
    # 解包为16bit数组
    img = np.zeros(width * height, dtype=np.uint16)
    for i in range(0, len(data), 5):
        p = i // 5 * 4
        img[p]   = (data[i] << 2) | (data[i+1] >> 6)
        img[p+1] = ((data[i+1] & 0x3F) << 4) | (data[i+2] >> 4)
        img[p+2] = ((data[i+2] & 0x0F) << 6) | (data[i+3] >> 2)
        img[p+3] = ((data[i+3] & 0x03) << 8) | data[i+4]
    return img.reshape(height, width)

# ---------- ISP基础处理 ----------
def black_level_correction(raw, black_level=64):
    """黑电平校正: 减去黑电平并归一化到10bit范围"""
    corrected = np.clip(raw.astype(np.int32) - black_level, 0, 1023)
    return (corrected * 255 // 1023).astype(np.uint8)

def white_balance(img, r_gain=1.8, b_gain=1.5):
    """白平衡: 对R/B通道施加增益"""
    b, g, r = cv2.split(img)
    r = np.clip(r * r_gain, 0, 255).astype(np.uint8)
    b = np.clip(b * b_gain, 0, 255).astype(np.uint8)
    return cv2.merge([b, g, r])

def demosaic_and_convert(bayer_img):
    """Bayer RGGB转BGR: 去马赛克 + 色彩空间转换"""
    # OpenCV默认BayerBG对应RGGB排列
    bgr = cv2.cvtColor(bayer_img, cv2.COLOR_BayerBG2BGR)
    return cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)

# ---------- 主流程 ----------
def raw_to_standard_image(raw_path, output_path):
    """完整RAW转标准图像流程"""
    # 1. 读取并解析RAW
    raw = read_raw10_packed(raw_path)
    # 2. 黑电平校正
    img_8bit = black_level_correction(raw)
    # 3. 白平衡
    img_wb = white_balance(img_8bit)
    # 4. 去马赛克 + 色彩转换
    result = demosaic_and_convert(img_wb)
    # 5. 保存结果
    cv2.imwrite(output_path, result)
    print(f"处理完成,输出: {output_path}")
    return result

if __name__ == "__main__":
    import sys
    if len(sys.argv) != 3:
        print("用法: python raw_converter.py <输入.raw> <输出.png>")
        sys.exit(1)
    raw_to_standard_image(sys.argv[1], sys.argv[2])

运行与验证

  1. 准备输入:将相机输出的10bit packed RAW文件命名为input.raw,确保分辨率1920×1080、Bayer模式RGGB。
  2. 执行转换:python raw_converter.py input.raw output.png
  3. 验证标准:程序正常结束并输出output.png;用图像查看器打开,图像无明显偏色、无棋盘格伪影,物体边缘清晰无彩虹纹。若图像偏暗,可适当降低black_level参数;若偏色,调整r_gain/b_gain。

关键说明

  • RAW解析中每5字节存储4个10bit像素,移位操作需严格按packed顺序进行,否则图像会出现错位条纹。
  • OpenCV的COLOR_BayerBG2BGR对应RGGB排列,若实际Bayer模式不同需相应调整转换标志。
  • 本流程未包含镜头阴影校正、降噪等高级ISP模块,输出为后续处理的基础输入。
RAW文件 10bit packed 解析解包 → uint16 Bayer 黑电平校正 减偏移→8bit 白平衡 R/B增益 去马赛克 → BGR输出