單元 5 · 第一個鏡頭跑起來

rpicam-apps 完整流程、RAW/DNG

5.1 啟用相機

raspi-config(RPi OS)
$ sudo raspi-config
  選單:Interface Options → Camera → Enable → Finish
$ sudo reboot

RPi5 的 Raspberry Pi OS 預設已啟用相機;此步驟為保險。Bookworm 後的 libcamera 不需要「camera=1」舊設定。

5.2 確認偵測(含輸出逐欄解讀)

rpicam-hello --list-cameras
$ 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:可用串流模式與解析度
order 迷思(先記住):這裡顯示 SGBRG10_CSI2PCSI 傳輸層的 fourcc;OV5647 實際是 RGGB。驅動在內核層做了 order 轉換。你手動解析 RAW 時以 RGGB 為準(單元 8 驗證)。

5.3 預覽 / 拍照 / 錄影(關鍵旗標全表)

基本三指令
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
RAW 的意義(再次強調):DNG = Bayer RAW 封裝。所有品質分析(黑位、雜訊、色彩、Bayer order)都必須回到 RAW——ISP 處理過就「回不去」。養成習慣:rpicam-still --raw -o t.dng

5.4 調校用「固定參數」拍照(範本)

固定曝光/增益/AWB 拍 RAW
rpicam-still --raw -o fixed.dng     --shutter 20000 --gain 1.0     --awb off --awbgains 1.0,1.0

固定參數的目的是「重現同一個畫面」:不同時間拍的 RAW 才有可比性(單元 14 回歸用)。

5.5 觀察 AE 狀態(調校前置)

--info 輸出節錄
$ rpicam-still --info -o /dev/null
...
ExposureTime: 33333
AnalogueGain: 1.5
ColourGains: [1.7, 1.3]
...

這告訴你「自動模式下感測器目前的曝光/增益/AWB gains」——是理解場景曝光需求的依據。

5.6 picamera2 完整程式

控制曝光/AWB 拍照
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()

5.7 常見失敗快速對照

症狀方向詳見
list-cameras 空overlay / 排線 / dmesg單元 1/6
預覽全黑曝光 0?AE 沒跑?鏡頭蓋?單元 10
明暗條紋(banding)曝光與 50/60Hz 不同步單元 10
色彩全錯Bayer order / AWB 未校正單元 8/11
預覽卡頓/掉幀解析度過高、HDMI 預覽慢降解析度

5.8 深入:rpicam-apps 的完整旗標解讀

除了基本拍照,rpicam-apps 是調校的「瑞士刀」:

旗標作用調校場景
--brightness/--contrast/--saturation簡易調整快速試
--evEV 補償AE 偏移
--metering測光模式背光場景
--awbAWB 模式固定色溫
--shutter/--gain固定曝光可重現測試
--tuning-file指定 tuning 檔A/B 測試 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

5.9 練習:建立你的「標準測試拍攝」腳本

test_capture.sh
#!/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)"
  1. 建立並執行上述腳本。
  2. 確認 test.dng 產生。
  3. 記錄「你看到的畫面」與「RAW 存在」兩件事。
看完這單元你應該能說出:
  • 啟用相機並逐欄讀懂 list-cameras。
  • rpicam-apps 旗標全表與調校用法。
  • 固定參數拍 RAW 的意義與範本。
  • 用 --info 觀察 AE 狀態。
  • picamera2 控制曝光/AWB。

進階真實情境 Worked Example:用 rpicam-apps 比較兩個 tuning 檔的差異

場景:你手上有兩版 tuning 檔(v1=出廠預設、v2=你手動調整過 NR/Sharpen),需要量化比較兩者在相同場景下的差異。

A/B tuning 比較腳本
#!/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
為什麼選這條路徑:用 --tuning-file 可以在完全相同的曝光條件下比較兩個 tuning 檔的效果。配合 --awb off 和 --awbgains 1,1 可以排除 AWB 干擾,純粹比較 ISP 參數(NR/Sharpen/CCM)的差異。這是 tuning 迭代的基本功——沒有 A/B 比較,你不知道改動是否真的改善了畫質。

深入原理擴充:rpicam-apps 與 libcamera 的控制抽象層

rpicam-apps 是 libcamera 的前端應用,但它對控制的處理比你想的複雜:

大家以為沒問題但其實是陷阱:很多人以為「rpicam-still --raw 拍的 RAW 完全不受 ISP 影響」,但實際上 libcamera 在存 DNG 前已經套用了部分 metadata(如 BlackLevel、AsShotNeutral)。若你要做「純淨 RAW 分析」,需要從 v4l2-ctl 直接擷取,而非透過 rpicam-apps——這在後續單元 8 的 RAW 驗證中很重要。

診斷式疑難排解表

症狀可能原因解決方案
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 為 0libcamera 版本過舊,未正確寫入 DNG metadata升級 libcamera(sudo apt upgrade libcamera);或手動在 DNG 中修正 black_level

進階挑戰題

  1. 寫一個 Python 腳本,自動化「固定曝光/增益拍攝 → rawpy 讀取 → 計算各通道均值/標準差」的完整流程,輸出 CSV 報告。
  2. 用 rpicam-still 的 --info 輸出,追蹤 AE 收斂過程:每秒拍一張並記錄 ExposureTime/AnalogueGain,畫出收斂曲線。
  3. 若要確保「不同時間拍的 RAW 可比較」,除了固定曝光/增益/AWB 外,還需要控制哪些環境變數?

延伸閱讀

專案級端到端 Worked Example:標準測試拍攝管線專案

場景:所有後續調校(黑位/LSC/色彩/NR)都需要「可重現的拍攝」。本專案建立一套標準拍攝管線:固定參數、自動命名、產出 DNG + metadata 記錄,讓不同天拍的圖可以互相比較。整合單元 5(rpicam 旗標)、8(RAW)、14(版本管理)知識。

capture_pipeline.sh:標準拍攝系統
#!/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/
專案規模與跨單元整合:這套管線是整個調校工作流的「地基」:固定參數保證可重現(單元 5)、RAW 產出供所有品質分析(單元 8)、自動命名 + metadata 支撐版本管理(單元 14)。往後每個調校改動都走同一管線,才能做 A/B 比較。

量測/驗證 SOP:拍攝一致性驗證

  1. 固定相機、光源、拍攝距離與鏡頭設定。
  2. 用 capture_pipeline.sh 拍基準 RAW(室內日光燈,20000µs, gain 1)。
  3. 間隔 10 分鐘重拍一次,比較兩張 RAW 的 ROI 均值(差異 <5%)。
  4. 確認 metadata 檔記錄完整(時間、參數、場景)。
  5. --info 確認 AE/AWB 已關閉(無浮動)。
  6. 存檔並標記「基準」。
判讀指標:兩張 RAW 均值差 >5% = 光源或參數不穩,重拍;--info 出現非預期 ExposureTime = AE 沒關乾淨。一致性的目標是「同一場景,今天拍的與三個月後拍的可以比較」。

平台間對照:標準拍攝工具

面向RPi5Orange PiOrin NanoThor
拍照 CLIrpicam-still(成熟)gst-launch / v4l2-ctlargus_camera / nvgstcaptureargus / Holoscan
RAW 輸出--raw 自動 DNG(含 metadata)v4l2 裸 RAW(手解).nvraw(需轉換).nvraw / Holoscan
固定參數--shutter/--gain/--awb off(簡單)v4l2-ctl 手動設--exp-time/--gain 可設SensorMode 設定
DNG metadata 可能誤寫無 metadata 標準raw 格式私有工具新、文件少

互動式檢核清單


第 3 輪深度加深

① Register 位元級完整工作流:OV5647 完整初始化序列(簡化版)

步驟暫存器範圍目的關鍵 bit
1. Reset0x0103 = 0x01軟體 resetbit[0] = SW reset, 等 10ms
2. Chip ID 驗證0x300A = 0x56, 0x300B = 0x47確認感測器回應
3. PLL 設定0x3034-0x3037設定 pixel clock0x3034 bit[7:6]=PLL mode, 0x3037 bit[4]=PLL root div
4. 時序設定0x3800-0x3821H/V 整合開始/結束bit[11:0] = pixel 起始/結束位置
5. 輸出格式0x4300 = 0xF0RAW Bayer 10-bitbit[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 損壞

③ 量測驗證完整 SOP:首次影像品質快速評估

  1. 拍攝條件:5000K 光源箱、18% 灰卡、三腳架、手動曝光 10ms、ISO 100
  2. 量測項目:
    a. 平均亮度(mean pixel value):預期 80-120 (8-bit scale)
    b. 平均偏色(R-G, B-G):各 <10
    c. 暗角比(四角 mean / 中心 mean):>0.85 為合格
    d. 銳利度(水平邊緣 MTF10):>0.3 LP/pixel
  3. 工具:rawpy + numpy + scipy.ndimage
  4. 判讀:四項全通過 = 首次影像 OK;任一不通過 = 對應單元深入排查
  5. 常見偏差:色溫偏差 → AWB 未啟用;暗角嚴重 → 鏡頭未對準

④ 四平台終極對照

面向RPi5Orange PiOrin NanoThor推薦
首次啟動步驟config.txt + dtoverlayDTB 編譯 + overlayNV flashing + DTHoloscan YAML configRPi5 最簡單
首幀時間~2s~3s~5s~8sRPi5 最快
必要工具rpicam-appsgst + v4l2Jetson 相關套件Holoscan SDKRPi5 依賴最少
文件品質★★★★★★★★★★★★★RPi5 文件最完整

⑤ 完整 Bring-up 專案 Checklist