1. 初始化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排列一致。