rpicam-apps 完整流程、RAW/DNG
$ sudo raspi-config 選單:Interface Options → Camera → Enable → Finish $ sudo reboot
RPi5 的 Raspberry Pi OS 預設已啟用相機;此步驟為保險。Bookworm 後的 libcamera 不需要「camera=1」舊設定。
$ rpicam-hello --list-cameras
Available cameras
-----------------
0 : ov5647 [2592x1944 10-bit RGGB]
Modes: 'SGBRG10_CSI2P' : 640x480 1296x972 1296x730 2592x1944
'YUV420_8_CSI2P' : 640x480 1296x972 1296x730 2592x1944| 欄位 | 意義 |
|---|---|
0 : | 相機索引(多顆時依序編號) |
ov5647 | 感測器名稱(來自 DT compatible) |
2592x1944 10-bit RGGB | 最大解析度 / RAW 位元深 / Bayer order |
Modes: | 可用串流模式與解析度 |
SGBRG10_CSI2P 是CSI 傳輸層的 fourcc;OV5647 實際是 RGGB。驅動在內核層做了 order 轉換。你手動解析 RAW 時以 RGGB 為準(單元 8 驗證)。rpicam-hello -t 10000 # 預覽 10 秒 rpicam-still -o shot.jpg # 拍照 rpicam-vid -t 5000 -o video.h264 # 錄 5 秒 H.264
| 旗標 | 作用 | 調校常用 |
|---|---|---|
-t | 持續時間 ms | — |
-o | 輸出檔 | — |
--width/--height | 輸出解析度 | 固定測試解析度 |
--shutter | 固定快門 µs | ✅ 固定曝光 |
--gain | 固定增益 | ✅ 固定增益 |
--awb off --awbgains r,b | 關 AWB 並手動 gains | ✅ 中性色彩 |
--raw | 額外輸出 RAW(DNG) | ✅ 調校必用 |
--info | 印出控制與統計 | ✅ 觀察 AE |
rpicam-still --raw -o t.dng。rpicam-still --raw -o fixed.dng --shutter 20000 --gain 1.0 --awb off --awbgains 1.0,1.0
固定參數的目的是「重現同一個畫面」:不同時間拍的 RAW 才有可比性(單元 14 回歸用)。
$ rpicam-still --info -o /dev/null ... ExposureTime: 33333 AnalogueGain: 1.5 ColourGains: [1.7, 1.3] ...
這告訴你「自動模式下感測器目前的曝光/增益/AWB gains」——是理解場景曝光需求的依據。
from picamera2 import Picamera2
picam2 = Picamera2()
cfg = picam2.create_still_configuration()
picam2.configure(cfg)
picam2.set_controls({
"AeEnable": False, # 關自動曝光
"ExposureTime": 20000, # 快門 µs
"AnalogueGain": 1.5,
"AwbEnable": False, # 關自動白平衡
"ColourTemperature": 4500, # 手動色溫
})
picam2.start()
picam2.capture_file("shot.jpg")
picam2.stop()| 症狀 | 方向 | 詳見 |
|---|---|---|
| list-cameras 空 | overlay / 排線 / dmesg | 單元 1/6 |
| 預覽全黑 | 曝光 0?AE 沒跑?鏡頭蓋? | 單元 10 |
| 明暗條紋(banding) | 曝光與 50/60Hz 不同步 | 單元 10 |
| 色彩全錯 | Bayer order / AWB 未校正 | 單元 8/11 |
| 預覽卡頓/掉幀 | 解析度過高、HDMI 預覽慢 | 降解析度 |
除了基本拍照,rpicam-apps 是調校的「瑞士刀」:
| 旗標 | 作用 | 調校場景 |
|---|---|---|
--brightness/--contrast/--saturation | 簡易調整 | 快速試 |
--ev | EV 補償 | AE 偏移 |
--metering | 測光模式 | 背光場景 |
--awb | AWB 模式 | 固定色溫 |
--shutter/--gain | 固定曝光 | 可重現測試 |
--tuning-file | 指定 tuning 檔 | A/B 測試 tuning |
rpicam-still --tuning-file v1.json --shutter 20000 --gain 1 -o v1.jpg rpicam-still --tuning-file v2.json --shutter 20000 --gain 1 -o v2.jpg
#!/bin/bash # 固定參數拍 RAW,供後續所有單元使用 rpicam-still --raw -o test.dng \ --shutter 20000 --gain 1.0 --awb off --awbgains 1.0,1.0 echo "已存 test.dng(RAW)"
場景:你手上有兩版 tuning 檔(v1=出廠預設、v2=你手動調整過 NR/Sharpen),需要量化比較兩者在相同場景下的差異。
#!/bin/bash # 固定參數拍攝,比較 tuning 效果 SHUTTER=20000 GAIN=1.0 # v1(預設 tuning) rpicam-still --raw --shutter $SHUTTER --gain $GAIN \ --awb off --awbgains 1,1 \ --tuning-file /usr/share/libcamera/ipa/rpi/pisp/ov5647.json \ -o compare_v1.jpg # v2(手動 tuning) rpicam-still --raw --shutter $SHUTTER --gain $GAIN \ --awb off --awbgains 1,1 \ --tuning-file ./my_tuning_v2.json \ -o compare_v2.jpg echo "拍攝完成,比較兩張圖的差異" ls -la compare_v1.jpg compare_v2.jpg
rpicam-apps 是 libcamera 的前端應用,但它對控制的處理比你想的複雜:
ExposureTime(µs),libcamera 內部會換算成感測器的曝光行數。若行數超出 frame length 限制,libcamera 會自動截斷而非報錯——你設 50ms 但實際可能只曝光 33ms。AnalogueGain(線性值),驅動會查 gain map 轉成暫存器值。OV5647 的 gain map 是非線性的——gain=2.0 不代表訊號強度是 gain=1.0 的兩倍。| 症狀 | 可能原因 | 解決方案 |
|---|---|---|
| rpicam-still --raw 拍出的 DNG 用 rawpy 讀取時報錯 | DNG 格式版本不相容或 rawpy 版本過舊 | 升級 rawpy(pip install -U rawpy);確認 DNG 是 libcamera 產生的標準格式 |
| --tuning-file 指定後畫面反而變差 | tuning 檔的 format/version 與當前 libcamera 版本不匹配 | 先用預設 tuning 確認基線;diff 比對你的 tuning 與預設差異 |
| rpicam-hello 預覽正常但 rpicam-still 拍出全黑 | AE 在拍照瞬間收斂到錯誤值,或 --shutter 設太低 | 加 --info 確認曝光值;用固定 --shutter 排除 AE 干擾 |
| picamera2 拍出的圖比 rpicam-still 暗 | picamera2 的 default tuning 與 rpicam-apps 不同 | 用 --tuning-file 指定同一個 tuning 檔確保一致性 |
| DNG 檔的 metadata 裡 black_level 為 0 | libcamera 版本過舊,未正確寫入 DNG metadata | 升級 libcamera(sudo apt upgrade libcamera);或手動在 DNG 中修正 black_level |
場景:所有後續調校(黑位/LSC/色彩/NR)都需要「可重現的拍攝」。本專案建立一套標準拍攝管線:固定參數、自動命名、產出 DNG + metadata 記錄,讓不同天拍的圖可以互相比較。整合單元 5(rpicam 旗標)、8(RAW)、14(版本管理)知識。
#!/bin/bash # 用法:./capture_pipeline.sh <標籤> [shutter] [gain] TAG=${1:-test}; SHUTTER=${2:-20000}; GAIN=${3:-1.0} OUT=shots/$(date +%Y%m%d_%H%M%S)_${TAG} mkdir -p shots # 固定曝光/增益/AWB,拍 RAW(單元 5 範本) rpicam-still --raw -o ${OUT}.dng \ --shutter $SHUTTER --gain $GAIN --awb off --awbgains 1.0,1.0 # 同時寫入 metadata(場景、條件) cat > ${OUT}.meta <<EOF date: $(date) tag: $TAG shutter_us: $SHUTTER gain: $GAIN awb: off (1.0,1.0) scene: (填寫:室內日光燈 / 日光 / 逆光 / 低光) EOF # 立即用 rawpy 驗證 RAW 可讀且非全黑 python3 - <50, "RAW 太暗,檢查曝光" print("RAW 驗證通過") EOF echo "已產出 ${OUT}.dng + ${OUT}.meta"
./capture_pipeline.sh indoor_a 20000 1.0 # 預期輸出: # shape=(1944, 2592) mean=512 # RAW 驗證通過 # 已產出 shots/20260817_101530_indoor_a.dng + .meta ls shots/
--info 確認 AE/AWB 已關閉(無浮動)。--info 出現非預期 ExposureTime = AE 沒關乾淨。一致性的目標是「同一場景,今天拍的與三個月後拍的可以比較」。| 面向 | RPi5 | Orange Pi | Orin Nano | Thor |
|---|---|---|---|---|
| 拍照 CLI | rpicam-still(成熟) | gst-launch / v4l2-ctl | argus_camera / nvgstcapture | argus / Holoscan |
| RAW 輸出 | --raw 自動 DNG(含 metadata) | v4l2 裸 RAW(手解) | .nvraw(需轉換) | .nvraw / Holoscan |
| 固定參數 | --shutter/--gain/--awb off(簡單) | v4l2-ctl 手動設 | --exp-time/--gain 可設 | SensorMode 設定 |
| 坑 | DNG metadata 可能誤寫 | 無 metadata 標準 | raw 格式私有 | 工具新、文件少 |
| 步驟 | 暫存器範圍 | 目的 | 關鍵 bit |
|---|---|---|---|
| 1. Reset | 0x0103 = 0x01 | 軟體 reset | bit[0] = SW reset, 等 10ms |
| 2. Chip ID 驗證 | 0x300A = 0x56, 0x300B = 0x47 | 確認感測器回應 | — |
| 3. PLL 設定 | 0x3034-0x3037 | 設定 pixel clock | 0x3034 bit[7:6]=PLL mode, 0x3037 bit[4]=PLL root div |
| 4. 時序設定 | 0x3800-0x3821 | H/V 整合開始/結束 | bit[11:0] = pixel 起始/結束位置 |
| 5. 輸出格式 | 0x4300 = 0xF0 | RAW Bayer 10-bit | bit[7:4] = 資料格式 |
| 6. ISP 控制 | 0x5001 = 0xFF | 啟用 ISP 全部區塊 | 每個 bit 啟用一個 ISP 模組 |
決策樹 A:rpicam-hello 出現 but 畫面全黑
畫面全黑 ├─ 檢查 A:overlay 是否已更新(重啟後 dmesg 有無新 probe) │ ├─ 無 →sudo raspi-config或手動改 config.txt 重啟 │ └─ 有 → 繼續 ├─ 檢查 B:rpicam-hello -k --nopreview -t 5000 --raw有無 RAW 檔 │ ├─ 有 RAW 且非全黑 → preview 問題,非 sensor 問題 │ └─ RAW 全黑 → sensor 無輸出 ├─ 檢查 C:手動設定曝光(排除 AE 問題) │ ├─ 手動曝光有畫面 → AE tuning 問題 │ └─ 手動曝光仍全黑 → sensor 硬體問題 └─ 檢查 D:檢查 GPIO 供電(A09 / cam1_reg / cam0_reg) ├─ 無 2.8V / 1.8V → 電源模組異常 └─ 供電正常 → sensor 損壞
| 面向 | RPi5 | Orange Pi | Orin Nano | Thor | 推薦 |
|---|---|---|---|---|---|
| 首次啟動步驟 | config.txt + dtoverlay | DTB 編譯 + overlay | NV flashing + DT | Holoscan YAML config | RPi5 最簡單 |
| 首幀時間 | ~2s | ~3s | ~5s | ~8s | RPi5 最快 |
| 必要工具 | rpicam-apps | gst + v4l2 | Jetson 相關套件 | Holoscan SDK | RPi5 依賴最少 |
| 文件品質 | ★★★★★ | ★★ | ★★★★ | ★★ | RPi5 文件最完整 |
rpicam-hello --list-cameras 確認 camera 列出rpicam-hello -k --nopreview -t 5000 確認有影像