1. 初始化ISP Pipeline并捕获RAW图像

初始化ISP Pipeline并捕获RAW图像 学习卡片

任务目标

在瑞芯微平台(RK3588/RV1126等)上,通过Media Controller框架配置RKISP驱动,初始化RAW图像采集pipeline,捕获一帧RAW图像并保存为DNG文件,以验证ISP基本通路是否正常。

环境依赖

  • 硬件:瑞芯微平台(RK3588/RV1126等),接入MIPI/Parallel摄像头传感器
  • 内核:启用Rockchip ISP驱动(CONFIG_VIDEO_ROCKCHIP_ISP)及对应传感器驱动
  • 用户空间工具:media-ctl、v4l2-ctl(v4l-utils包)
  • 文件系统:/dev/media*、/dev/video*设备节点存在

实现步骤

整体流程为:查询media拓扑 → 配置传感器格式与ISP链路 → 设置V4L2格式 → 申请帧缓冲 → 入队并等待数据 → 将RAW数据封装为DNG。以下脚本完成从初始化到保存DNG的完整闭环。

关键完整代码

#!/bin/bash
# capture_raw_dng.sh - 初始化ISP pipeline并捕获RAW图像保存为DNG
set -e

# ========== 配置区(按实际平台修改) ==========
MEDIA_DEV="/dev/media0"
SENSOR_ENTITY="m00_b_ov5647 0-0036"   # 传感器实体名(media-ctl -p查看)
ISP_MAIN_PATH="rkisp_mainpath"         # ISP主通路video节点
OUTPUT_FILE="capture_$(date +%Y%m%d_%H%M%S).dng"
WIDTH=1920
HEIGHT=1080
# =============================================

# 1. 查询当前media拓扑(调试用,确认实体名称)
echo "=== Media拓扑 ==="
media-ctl -d "$MEDIA_DEV" -p | grep -E "entity|pad0|pad1" | head -20

# 2. 配置传感器输出格式(以SBGGR10_1X10为例,RAW10 Bayer)
media-ctl -d "$MEDIA_DEV" -V "\"$SENSOR_ENTITY\":0[fmt:SBGGR10_1X10/${WIDTH}x${HEIGHT}]"

# 3. 建立传感器→ISP链路并设置ISP输入格式
media-ctl -d "$MEDIA_DEV" -l "\"$SENSOR_ENTITY\":0 -> \"rkisp-isp-subdev\":0[1]"
media-ctl -d "$MEDIA_DEV" -V "\"rkisp-isp-subdev\":0[fmt:SBGGR10_1X10/${WIDTH}x${HEIGHT}]"
media-ctl -d "$MEDIA_DEV" -V "\"rkisp-isp-subdev\":2[fmt:SBGGR10_1X10/${WIDTH}x${HEIGHT}]"

# 4. 设置ISP主通路输出格式(RAW数据,无ISP处理)
v4l2-ctl -d "$ISP_MAIN_PATH" --set-fmt-video=width="$WIDTH",height="$HEIGHT",pixelformat=RGGB

# 5. 申请4个帧缓冲并开始流式采集,捕获1帧后停止
v4l2-ctl -d "$ISP_MAIN_PATH" --set-ctrl=vertical_flip=0 --stream-mmap=4 --stream-count=1 \
    --stream-to="$OUTPUT_FILE.raw"

echo "已捕获RAW数据: $OUTPUT_FILE.raw ($WIDTH x $HEIGHT)"

# 6. 将RAW数据封装为DNG(使用Python + rawpy/tifffile)
python3 << EOF
import numpy as np
import tifffile
import rawpy

width, height = $WIDTH, $HEIGHT
raw_data = np.fromfile("$OUTPUT_FILE.raw", dtype=np.uint16).reshape(height, width)

# DNG要求Bayer模式与CFA配置一致(RGGB对应模式0)
tifffile.imwrite(
    "$OUTPUT_FILE",
    raw_data,
    photometric='CFA',
    planarconfig='contig',
    metadata={
        'Make': 'Rockchip',
        'Model': 'RKISP',
        'CFARepeatPatternDim': (2, 2),
        'CFAPattern': [0, 1, 1, 2],  # RGGB
        'BlackLevel': 64,
        'WhiteLevel': 1023,          # 10-bit RAW
    }
)
print("DNG已保存: $OUTPUT_FILE")
EOF

# 7. 清理临时RAW文件
rm -f "$OUTPUT_FILE.raw"
echo "完成。验证: identify $OUTPUT_FILE 或 python3 -c \"import rawpy; rawpy.imread('$OUTPUT_FILE')\""

运行方式

chmod +x capture_raw_dng.sh
./capture_raw_dng.sh

验证方法与通过条件

  • 链路检查:运行后无报错,且media-ctl查询显示传感器→ISP链路为[1]使能状态。
  • 文件生成:当前目录生成capture_*.dng文件,大小约为 WIDTH × HEIGHT × 2 字节(1920×1080≈4.1MB)。
  • 数据有效性:执行以下命令能正常读取且图像非全黑/全白:
python3 -c "
import rawpy, numpy as np
raw = rawpy.imread('capture_*.dng')
img = raw.raw_image
print(f'RAW尺寸: {img.shape}, 像素范围: [{img.min()}, {img.max()}]')
assert img.min() < 200 and img.max() > 800, '像素范围异常,检查传感器曝光'
print('DNG验证通过')"

若像素范围接近[64,64](全黑)或[1023,1023](全饱和),说明传感器配置或曝光异常,需检查传感器驱动和ISP输入格式。

常见问题

  • 实体名不匹配:先运行media-ctl -d /dev/media0 -p查看实际传感器实体名,替换脚本中SENSOR_ENTITY。
  • 格式不支持:传感器可能输出SBGGR8或SBGGR12,用v4l2-ctl --list-formats-ext确认后修改fmt:参数。
  • DNG打开失败:确认tifffile和rawpy已安装(pip install tifffile rawpy),且CFAPattern与传感器Bayer排列一致。