單元 10 · 曝光與自動曝光(AE)

Argus 曝光控制

曝光三要素

要素控制注意
快門時間感測器曝光 register(tegracam)太長模糊/banding
類比增益感測器 AGC太高雜訊
數位增益NVIDIA ISP最後手段

透過 Argus 控制

Argus SensorMode(示意)
SensorMode ... exp_time = 20000   # 微秒
SensorMode ... gain = 2.0

也可用 v4l2-ctl -d /dev/v4l-subdev0 -C exposure

NVIDIA AE 收斂

自動收斂:NVIDIA AE 依 ISP 統計自動調整。除錯「過暗」→ 確認 AE 是否卡在快門/增益上限——受限就補光或放寬範圍設定。

10.6 深入:曝光 register 與 Worked Example

讀目前曝光
v4l2-ctl -d /dev/v4l-subdev0 -C exposure

曝光值依感測器位元布局組合(單元 3 的 16-bit 位址規則)。正式流程用驅動/平台控制,這裡只是理解。

控制曝光
argus_camera SensorMode exp_time=20000
順序鐵則:先快門 → 類比增益 → 數位增益。用增益補曝光犧牲畫質。

10.7 練習

  1. 讀目前曝光/增益值。
  2. 手動設定並確認生效。
  3. 日光燈下檢查 banding。
看完這單元你應該能說出:
  • 曝光三要素。
  • Argus / tegracam 控制曝光。
  • NVIDIA AE 自動收斂。
  • 「上限受限」除錯方向。

10.8 深入原理:曝光時間的 register 位元級組合

OV 系感測器的曝光時間是 20-bit,拆在多個 register(如 0x3500/0x3501/0x3502/0x3503),組合方式依 datasheet 而定。這代表「讀回的值」要自己組合,不是單一 register 就能看。

組合曝光時間(示意)
# 讀三個位元組
hi = i2cget(0x3500); mid = i2cget(0x3501); lo = i2cget(0x3502)
exp = (hi << 12) | (mid << 4) | (lo >> 4)   # 依 datasheet 的位元布局
為什麼不直接手動組合:正式流程一律用 tegracam / Argus 的曝光 control——它知道位元布局並處理量綱。這裡只是讓你理解「register 層」長什麼樣,出問題時知道去哪裡看。

10.9 Worked Example:手動曝光 + 增益做曝光階梯

曝光階梯(確認感測器響應線性)
# 固定增益,逐級拉曝光,看 RAW 亮度是否線性
for e in 1000 2000 4000 8000 16000 32000; do
  v4l2-ctl -d /dev/v4l-subdev0 -c exposure=$e
  argus_camera --mode 0 --capture-auto 1 --raw-file e$e.raw --duration 1
done
python3 - <<'EOF'
import numpy as np, glob
for f in sorted(glob.glob('e*.raw')):
    raw = np.fromfile(f, dtype=np.uint16)
    print(f, '亮度:', raw.mean().round(1))   # 應隨曝光倍增
EOF
判讀:亮度隨曝光「倍增而倍增」= 線性良好;若高曝光處「卡住不再亮」→ 感測器飽和(過曝)或黑位設定問題。

10.10 疑難排解決策樹:畫面過暗

決策樹
1. AE 是否開啟?
   ├─ 關 ─→ 曝光/增益是否太小?
   └─ 開 ┐
2. AE 是否卡在邊界?
   ├─ 快門卡上限 → 場景太暗:補光 / 放寬 max_exp
   ├─ 增益卡上限 → 補光(優先)或放寬 max_gain
   └─ 沒卡 ┐
3. 統計被騙?
   ├─ 場景大片黑/白 → 換場景或設 ROI
   └─ 正常 ┐
4. 檢查黑位設定 → 若黑位太高,暗部被扣光 → ✅ 修正

10.11 常見錯誤 / 陷阱

陷阱 ①:日光燈下用「長曝光」→ 50/60Hz banding——曝光需配合光源頻率(回顧單元 12/14 的 banding 檢查)。
陷阱 ②:補曝光不先加增益是對的,但「補到底」仍不夠亮就要補光,硬拉數位增益只會爆雜訊。
陷阱 ③:改變 mode(解析度/幀率)後,同一曝光數值對應的毫秒不同(回顧單元 2)——比較前先鎖定 mode。

10.12 練習

  1. 跑一次曝光階梯,確認線性範圍。
  2. 手動切 AE 開/關,比較兩種出圖。
  3. 寫下你的平台「max_exp / max_gain」的設定值。

10.13 進階:banding(條紋)的成因與對策

室內日光燈以 50Hz/60Hz 閃爍。曝光時間若不是光源週期的整數倍,畫面會出現明暗條紋(banding)——這是「曝光與光源頻率不匹配」,不是感測器壞。

光源頻率安全曝光對策
50Hz(台灣/歐陸)10ms 的整數倍曝光設 10ms/20ms…
60Hz(美國/日本)8.33ms 的整數倍曝光設 8.33/16.67ms…
除錯:看到橫向條紋先確認光源與曝光;短曝光(<10ms)更容易看到,長曝光反而不明顯——別誤判成雜訊或硬體問題。

10.14 快速參考:曝光除錯小抄

症狀方向
太暗且 AE 卡上限補光 / 放寬範圍
太亮且 AE 卡下限減光 / 縮範圍
忽亮忽暗統計被騙 / 震盪:調 ROI
橫向條紋banding:光源頻率對齊
高增益爆雜訊優先曝光與光源

10.15 看完本單元該記住的三件事

順序鐵則:光源 → 曝光 → 類比增益 → 數位增益。
NVIDIA AE 自動收斂,但會被統計騙、會被範圍卡。
比較前鎖定 mode,否則曝光「數字」不可比。

10.16 Worked Example:設定 AE 範圍

依場景設曝光/增益範圍
# 1. 量場景亮度:全遮 vs 全開的 RAW 均值
dark = mean(全遮)      # ~黑位
bright = mean(全開)    # 目標近半飽和
# 2. 決定目標亮度與曝光/增益範圍
#    - 長曝光上限:依 motion blur 需求
#    - 增益上限:依 SNR 預算(單元 13)
# 3. 在 DTB mode 或 runtime 設 max_exp / max_gain
# 4. 回歸:白天/夜晚/室內 都要在範圍內收斂
重點:範圍太寬 → AE 過度補償(亮場景過曝);太窄 → 暗場景卡上限。範圍要「配合真實場景」來定,而不是隨便填。

10.17 看完本單元該記住的三件事

曝光三要素的優先順序是鐵則。
AE 自動但會卡範圍、會被統計騙。
banding、mode 一致性是常見陷阱。

延伸閱讀

10.10 進階真實情境 Worked Example:OV9281 在工業場景的 AE 收斂策略

場景:OV9281 裝在傳送帶上方做缺陷檢測,光源固定但產品表面反射率差異大(亮白色金屬 vs 暗色橡膠)。AE 需要在不同產品間快速收斂。

Argus AE 參數調校
# 1. 設定 AE 為手動模式(固定曝光)
argus_camera --mode 0 --ae-manual --exposure-time 10000 --gain 1.0
# 2. 觀察不同產品的亮度
#    亮色金屬:histogram 偏右 → 可能過曝
#    暗色橡膠:histogram 偏左 → 可能欠曝
# 3. 改用 auto exposure,設定收斂範圍
argus_camera --mode 0 --ae-auto \
  --ae-convergence-speed fast \
  --ae-target-brightness 128 \
  --ae-min-exposure 1000 \
  --ae-max-exposure 33000
# target-brightness=128:AE 試圖讓平均亮度到 128/255
# convergence-speed=fast:快速跟上產品變化

設計決策:工業場景的 AE 與一般監控不同——產品每幾秒換一種,AE 需要「快速收斂但不震盪」。Argus 的 convergence-speed 控制 PID 控制器的 response time。

2.11 深入原理擴充:Argus AE 的 PID 控制器內部

Argus AE 的核心是一個 PID(比例-積分-微分)控制器,它根據 histogram 的亮度分佈調整曝光時間和 gain。

PID 參數功能過大的效果
P(比例)亮度偏離目標時的反應速度曝光值震盪(over/under shoot)
I(積分)消除長期偏差收斂變慢(因為「等待」積分累積)
D(微分)抑制震盪反應遲鈍(過度抑制變化)
陷阱:「ae-convergence-speed 設 fast 就一定好」——fast 模式下 P 值較大,在「高對比場景」(例如畫面同時有很亮和很暗區域)會造成曝光值劇烈震盪,畫面忽明忽暗。這時反而需要 medium 或 slow。

10.11 診斷式疑難排解表

症狀可能原因解決方案
AE 開啟後畫面忽明忽暗(震盪)convergence-speed 太快 或 target-brightness 不合理降低 convergence-speed;確認 target-brightness 在 100-150 範圍
AE 在低光下無法收斂(永遠拉長曝光)max-exposure-time 設太低 或 sensor 幀率限制提高 max-exposure-time;降低 fps 以允許更長曝光
AE 在高光下過曝(histogram 爆掉)min-exposure-time 設太高 或 gain 未降降低 min-exposure-time 到 sensor 支援下限
手動設定曝光後畫面比 auto 更暗手動曝光值低於 auto 的收斂目標用手動模式測出「正確曝光」的參數,再切回 auto 作為參考
AE 在室內/室外切換時需要很長時間收斂I 參數過大(積分太慢消除偏差)在已知場景切換點,用 event trigger 強制 reset AE

10.12 進階挑戰題

  1. 用 Argus 手動設定不同的曝光時間 + gain 組合,畫出 OV9281 的「亮度-曝光時間」關係圖(含不同 gain 值的曲線族)。
  2. 設計一個「AE 收斂時間測試」:在已知的明暗切換點(例如用 LED 燈開/關),計時 AE 從一個亮度目標到另一個目標的收斂時間。
  3. 若你的場景有「週期性亮度變化」(例如旋轉物體的反光),設計一個 AE 策略使畫面亮度保持穩定(提示:考慮 AE 的 response time 與週期的關係)。

10.13 專案級端到端 Worked Example:產線 AE 收斂最佳化專案

場景:傳送帶缺陷檢測(回顧 10.10 場景)產品每幾秒更換,AE 要不斷重收斂,且要同時避免 banding 與震盪。專案目標:系統化調出「收斂快、不震盪、無 banding」的 AE 參數組。

專案流程
# Step 1 · 鎖定光源與曝光基準(排除 AE 干擾)
#   量光源頻率(50Hz / 60Hz)→ 決定安全曝光(回顧 10.13)
# Step 2 · 測曝光階梯 + SNR 預算 → 定 max_gain(回顧 13.6)
# Step 3 · 設定 AE 範圍:min/max exp、max gain、target brightness
argus_camera --mode 0 --ae-auto \
  --ae-target-brightness 128 \
  --ae-convergence-speed medium \
  --ae-min-exposure 1000 --ae-max-exposure 33000
# Step 4 · 收斂測試:LED 開/關計時收斂秒數(回顧 10.12-2)
# Step 5 · 長跑回歸:不同產品連續跑 30 分鐘,檢查
#   有無震盪(忽亮忽暗)、有無 banding、有無卡邊界
# Step 6 · 把參數組寫進 DTB mode 或 runtime 設定,固化版本

專案輸出:AE 參數表(含範圍 / 目標 / 收斂速度)+ 收斂測試數據 + 30 分鐘長跑報告。

10.14 量測/驗證 SOP:曝光 / AE 驗證

  1. 讀現值v4l2-ctl -d /dev/v4l-subdev0 -C exposure / -C analogue_gain
  2. 曝光階梯:固定增益逐級拉曝光,驗證 RAW 亮度線性。
  3. banding 檢查:室內日光燈下檢查橫紋;曝光設光源週期整數倍。
  4. AE 收斂:明 / 暗切換,計時收斂幀數與是否震盪。
  5. 範圍邊界:確認 AE 在極暗 / 極亮場景是否卡 min / max。
  6. 順序紀律:光源 → 曝光 → 類比增益 → 數位增益。
驗收指標:曝光線性 R² > 0.98、收斂 < 1s 且無震盪、無 banding、極端場景不卡死。

10.15 平台間對照:曝光控制

面向Orin NanoRPi5Orange PiThor
曝光介面SensorMode exp_timelibcamera ExposureTimeV4L2 exposureSensorMode
增益介面SensorMode gainAnalogueGainanalogue_gainSensorMode
AE 演算法NVIDIA 閉迴路(PID)libcamera AGC 可改感測器內建NVIDIA 閉迴路
收斂控制convergence-speed調 AGC 參數有限convergence-speed
曝光單位微秒(µs)— 跨平台一致
重點:「順序鐵則」與「banding 對齊」是平台無關的;差異只在 AE 演算法的可視性——RPi5 可改演算法,Orin / Thor 只能調參數與範圍。

10.16 互動式檢核清單:曝光 / AE 驗收

10.14 Register 位元級完整工作流:AE 驗證——固定 vs 自動曝光

步驟Command預期(手動)預期(自動)
1. 手動曝光出圖argus --exposure-value 0.016 --gain-value 4.0 --capture-auto 0亮度固定N/A
2. 自動曝光出圖argus --capture-auto 1N/A亮度自適應
3. 直方圖比較Python hist()直方圖固定直方圖隨場景移動
4. 亮度穩定性30 幀 mean ± stdstd < 2std < 5(容許微調)
AE 完整驗證腳本:手動 vs 自動
#!/usr/bin/env python3
# ae_verify.py — 驗證 AE 功能
import numpy as np, subprocess, time

def capture(label, auto, exp=0.016, gain=4.0):
    cmd = [
        "argus_camera", "--camera-id", "0", "--mode", "0",
        "--capture-auto", "1" if auto else "0",
        "--duration", "1", "--output-dir", f"/tmp/ae_{label}"
    ]
    if not auto:
        cmd += ["--exposure-value", str(exp), "--gain-value", str(gain)]
    subprocess.run(cmd, capture_output=True)
    import glob
    raw = glob.glob(f"/tmp/ae_{label}/*.raw")
    return np.fromfile(raw[0], dtype=np.uint16) if raw else None

# Test 1: Fixed exposure
fixed = capture("fixed", auto=False)
print(f"Fixed exposure: mean={fixed.mean():.1f}")

# Test 2: Auto exposure
auto = capture("auto", auto=True)
print(f"Auto exposure: mean={auto.mean():.1f}")

# Test 3: Stability (30 frames auto)
means = []
for i in range(30):
    d = capture(f"stab_{i}", auto=True)
    means.append(d.mean())
    time.sleep(0.1)
means = np.array(means)
print(f"Stability: mean={means.mean():.1f} ± std={means.std():.2f}")

# Verdict
if means.std() < 5:
    print("AE VERDICT: PASS (stable)")
elif means.std() < 10:
    print("AE VERDICT: MARGINAL")
else:
    print("AE VERDICT: FAIL (unstable)")

10.15 多層疑難排解決策樹

決策樹 A:自動曝光不穩定(畫面忽明忽暗)
1. 曝光值在 ~0.016s 快速震盪?
   ├─ 是 → AE 目標值(target)過高 → 調低 target
   │       或 integration time 過短 → 加長最短曝光
   └─ 否 ┐
2. 偶爾一幀突然改變?
   ├─ 是 → 異常 frame 觸發重計算
   │       → 加 hysteresis(遲滯)
   └─ 否 ┐
3. 環境光源本身在閃爍?
   ├─ 是 → 加 flicker rejection(50/60Hz)
   └─ 否 → 降 convergence speed
決策樹 B:自動曝光過曝/過暗
1. 自動曝光後整體過亮?
   ├─ 是 → target luminance 太高 → 降低 target
   └─ 否 ┐
2. 自動曝光後整體過暗?
   ├─ 是 → target luminance 太低 → 提高 target
   └─ 否 ┐
3. 高光 blown(白色剪裁)?
   ├─ 是 → highlight 預算不足 → 用局部 AE / 包圍曝光
   └─ 否 → 整體亮度正確

10.16 量測驗證完整 SOP

  1. 手動基線:固定曝光 0.016s + 增益 4.0,取 RAW → mean ≈ 400。
  2. 自動出圖argus_camera --capture-auto 1 --duration 1
  3. 亮度自適應:遮擋鏡頭 → 亮度下降;打開 → 亮度上升。
  4. 穩定性:自動模式下連續 30 幀,量 mean ± std;std < 5 = PASS。
  5. 直方圖:手動 vs 自動的直方圖形狀差異;自動應趨向 target 分佈。
  6. 目標亮度:驗證自動模式下的平均亮度 ≈ target(預設 ~128 on 8-bit)。
  7. 收斂時間:從全遮→全開,量 mean 恢復時間;應 < 1 秒。
判讀標準:亮度隨場景自適應 ✓、std < 5 ✓、收斂 < 1 秒 ✓ = AE 功能正常。

10.17 四平台终极對照

面向Orin NanoRPi5Orange PiThor推薦
AE 實作3A library (NVIDIA)libcamera 3A感測器 AEC 硬體3A + Holoscan各有實現
AE 控制粒度極細(ROI / 區域)低(全局)極細 + AI量產 → Orin/Thor
Target 可調✅ 參數化✅ JSON tuning❌ 硬體固定✅ 參數化自訂 → Orin
收斂速度~0.5s~0.3s~0.2s~0.3s感測器 ISP 最快
Highlight 處理局部 AE / HDRHDR 模式有限局部 AE + AI高動態 → Orin/Thor
Flicker Rejection✅ 50/60Hz部分支援室內照明必開
ROI AE✅ 可程式化有限人臉追蹤 → Orin

10.18 完整 Bring-up 專案 Checklist