NVIDIA AWB/CCM
NVIDIA ISP 自動白平衡依統計調整 R/G/B gains,也可手動設定色溫。
AWB_AUTO / AWB_MANUAL + 色溫或 gains
Argus AWB_MANUAL + gains
色溫(開爾文)描述光源顏色:低色溫(3200K 鎢絲燈)偏橙紅,高色溫(6500K 日光)偏藍。感測器的 R/G/B 通道對各光源敏感度不同,AWB 算出每個通道的增益讓灰卡在影像中「看起來灰」。
| 光源 | 色溫 | R 增益傾向 | B 增益傾向 |
|---|---|---|---|
| 鎢絲燈 | ~3200K | 低(紅多) | 高 |
| 日光 | ~5500–6500K | 中 | 中 |
| 陰影/藍天 | ~7500K+ | 高 | 低 |
# 1. 關 AWB(固定 gains) Argus: AWB_MANUAL R_gain=1.0 B_gain=1.0 # 2. 拍灰卡,讀 R/G/B 平均 # (用 RAW 或 NV12 的灰卡區) python3 - <<'EOF' # r,g,b = 灰卡區三通道平均 # 目標 r' == g' == b' # 調整因子:R_new = R * (G/R), B_new = B * (G/B) EOF # 3. 寫回 gains,重拍確認 R≈G≈B Argus: AWB_MANUAL R_gain=1.12 B_gain=1.48 # 範例值
1. 整張偏紅/偏藍? ├─ 是 → AWB 光源估計錯:換場景/重校 └─ 否 ┐ 2. 局部偏色(角落)? ├─ 是 → 是 lens shading 造成 → 進 LSC(單元 12) └─ 否 ┐ 3. 特定色不準(綠不綠/皮膚怪)? ├─ 是 → CCM 色彩矩陣問題 → 需 tuning 資料 └─ 否 ┐ 4. 灰卡上 R≠G≠B? ├─ 是 → 重做 AWB 校正(11.9) └─ 否 → ✅ 色彩正常
灰卡校正的成敗在「灰卡是否真的中性」。常見誤差來源:灰卡髒污、光不均、反光、卡太小。校正時要求:卡佔畫面中央 30% 以上、光源均勻、避免眩光、相機正對卡。
# 校正後灰卡區 R/G/B 差異應 < 2%(同光源) r, g, b = 灰卡區三通道均值 print('R/G:', r/g, ' B/G:', b/g) # 應都接近 1.0 # 四角也抽樣:角落偏色 → 那是 LSC 的事(單元 12)
| 症狀 | 先查 |
|---|---|
| 整張偏紅/偏藍 | AWB 光源估計 |
| 角落偏色 | LSC 分通道(12) |
| 單色不準 | CCM / tuning |
| 灰卡 R≠G≠B | 重做 AWB 校正 |
| 混合色溫怪色 | 改手動色溫 |
CCM(色彩校正矩陣)把感測器 RGB 轉成目標色彩空間。判斷「要不要動 CCM」:拍標準色卡(如 Macbeth),看特定色塊誤差。
1. 拍標準色卡(灰卡校正 AWB 後) 2. 量 R/G/B/Y 等色塊的 RGB 值 3. 對照標準值算 ΔE 4. ΔE 大 → 需要 CCM 級校正(NVIDIA tuning) 5. ΔE 小 → 不用動,避免過度校正
場景:相機安裝在工廠入口,畫面同時有室內日光燈(色溫 ~4000K)和室外日光(~5500K)。AWB 需要在「兩種色溫共存」時保持自然。
# 1. 先讓 auto AWB 收斂(觀察它偏向哪種色溫) argus_camera --mode 0 --awb-auto --duration 5 # 2. 若 auto 偏向室外(日光範圍大),手動設定色溫 argus_camera --mode 0 --awb-manual --color-temperature 4500 # 3. 用灰卡量測 CCM 殘差 # 18% 灰卡 RGB 應接近 (128,128,128) # 若偏暖(R > B)→ 降低色溫設定 # 若偏冷(B > R)→ 提高色溫設定 # 4. 最終目標:灰卡在所有光源下色彩偏差 < 5%(ΔE < 5)
設計決策:混合光源是 AWB 的終極挑戰——auto AWB 只能「選一種」色溫當 white point。工業場景若光源穩定(日光燈+日光比例固定),手動設定色溫比 auto 更穩定。
CCM(Color Correction Matrix)不只是「調色彩」,它本質上是把感測器的「RGB 色域」映射到標準色彩空間(如 sRGB)。
| 步驟 | 說明 | 為什麼重要 |
|---|---|---|
| 1. 拍 24 色色卡 | 取得「感測器 RGB」vs「標準 XYZ」的對應 | 這是 CCM 計算的 input |
| 2. 計算 3×3 CCM | 最小二乘法求最佳映射 | CCM 的每行加總 ≈ 1(色彩守恆) |
| 3. 載入 ISP | 每個 pixel 都乘以 CCM | 即時校正,不耗 CPU |
| 症狀 | 可能原因 | 解決方案 |
|---|---|---|
| AWB 在日光燈下偏綠 | AWB 的 green 偏移未校正(或 CCM 的 green cross-talk 過大) | 用色卡重新計算 CCM;確認 CCM 的 green 行加總 ≈ 1 |
| AWB 在低光下偏紫 | 低光 gain 放大 UV 雜訊,AWB 誤判色溫 | 在低光下降低 AWB 靈敏度;或手動固定色溫 |
| 手動設定色溫後畫面偏黃 | 設定的色溫值不準確(燈具老化/型號差異) | 用色溫計量測實際光源色溫;或用灰卡校正 |
| AWB 在室內/室外切換時「跳色」 | AWB 的 response time 太快,對短暫色溫變化過度反應 | 提高 AWB 的 temporal smoothness;或用 hysteresis 避免頻繁切換 |
| CCM 載入後畫面色彩「過飽和」 | CCM 計算時色卡拍攝不標準(光源不均、角度不對) | 確保色卡在均勻光源下正對鏡頭拍攝;重算 CCM |
場景:產品要出貨,客戶要求色彩一致(ΔE < 5)。專案目標:完成「灰卡 AWB + 色卡 CCM」的完整色彩校準,並在多種光源下回歸。
# Phase 1 · 感測器中性化(先決條件) # 確認感測器端 AWB 關閉、黑位正確(回顧單元 8) # Phase 2 · 灰卡 AWB(每種光源各一次) argus_camera --mode 0 --raw-file gray_5500k.raw --duration 1 # 讀灰卡區 R/G/B,算 gains 讓 R≈G≈B(回顧 11.9) # 結果建表:5500K → R_gain / B_gain # Phase 3 · 色卡 CCM(每種光源各一次) argus_camera --mode 0 --raw-file cc_5500k.raw --duration 1 # 量 24 色塊 vs 標準值,最小二乘求 3×3 CCM(回顧 11.10) # Phase 4 · 驗證 # 重新拍灰卡 / 色卡,確認 R≈G≈B 且 ΔE < 5 # Phase 5 · 回歸 # 3200K / 5500K / 日光燈 三種光源全跑,記錄各光源的 gains + CCM
專案輸出:光源 →(AWB gains, CCM)對照表 + 每光源 ΔE 報告。這就是量產 firmware 要載入的色彩檔。
| 面向 | Orin Nano | RPi5 | Orange Pi | Thor |
|---|---|---|---|---|
| AWB 介面 | Argus AWB(auto/manual) | ColourGains | red / blue_balance | Argus AWB |
| CCM 載入 | NVIDIA tuning | tuning file | 感測器內建 | NVIDIA tuning |
| 手動色溫 | ✅ 可鎖定 | ✅ 可設定 | ⚠️ 有限 | ✅ 可鎖定 |
| 演算法可視性 | 低(黑箱) | 高(可改) | 低 | 低 |
| 校正工具 | 灰卡 / 色卡 + 自寫腳本全平台通用 | |||
| 步驟 | Command / 量測 | 預期(AWB ON) | 預期(AWB OFF) |
|---|---|---|---|
| 1. 灰卡出圖 | argus + X-Rite 灰卡 | R ≈ G ≈ B | 色偏(依光源) |
| 2. RGB ratio | mean(R)/mean(G), mean(B)/mean(G) | 均 ≈ 1.0 | 偏離 1.0 |
| 3. 色溫估計 | 色度座標 → 色溫 | ≈ 光源色溫 | 偏離光源色溫 |
| 4. 30 幀穩定性 | std of RGB ratio | std < 0.02 | 固定(std ≈ 0) |
#!/usr/bin/env python3 # awb_verify.py — 驗證白平衡功能 import numpy as np, subprocess, glob def capture_and_analyze(label): subprocess.run([ "argus_camera", "--camera-id", "0", "--mode", "0", "--capture-auto", "1", "--duration", "1", "--output-dir", f"/tmp/awb_{label}" ], capture_output=True) raw = glob.glob(f"/tmp/awb_{label}/*.raw") if not raw: return None data = np.fromfile(raw[0], dtype=np.uint16).reshape(800, 1280) r, g, b = data[0::2, 0::2], data[0::2, 1::2], data[1::2, 0::2] return {"R": r.mean(), "G": g.mean(), "B": b.mean()} # Test: Gray card under daylight result = capture_and_analyze("graycard") if result: rg = result["R"] / result["G"] bg = result["B"] / result["G"] print(f"R/G = {rg:.3f} (should be ~1.000)") print(f"B/G = {bg:.3f} (should be ~1.000)") deviation = abs(rg - 1.0) + abs(bg - 1.0) if deviation < 0.05: print("AWB VERDICT: PASS (neutral)") elif deviation < 0.10: print("AWB VERDICT: MARGINAL (slight cast)") else: print("AWB VERDICT: FAIL (color cast)")
1. 灰卡拍出偏暖(R > G > B)? ├─ 是 → 色溫估計過低 → 提高色溫 │ 或 CCM 暖色係數過高 → 降暖色增益 └─ 否 ┐ 2. 灰卡拍出偏冷(B > G > R)? ├─ 是 → 色溫估計過高 → 降低色溫 │ 或 CCM 冷色係數過高 → 降冷色增益 └─ 否 ┐ 3. 灰卡拍出偏綠? ├─ 是 → CCM 綠色通道增益過高 │ 或 AWB 色溫估計錯誤 └─ 否 → 色彩正常
1. 畫面色彩快速閃爍? ├─ 是 → AWB 收斂速度太快 → 降 speed │ 或光源 flicker → 開 flicker rejection └─ 否 ┐ 2. 色彩偶爾突然偏移? ├─ 是 → AWB 參考區域有異常色 → 限定 ROI └─ 否 ┐ 3. 色彩穩定但不準? ├─ 是 → 校正不足 → 執行白平衡校正 └─ 否 → AWB 正常
argus_camera --capture-auto 1 --duration 1 → 灰卡 RAW。| 面向 | Orin Nano | RPi5 | Orange Pi | Thor | 推薦 |
|---|---|---|---|---|---|
| AWB 實作 | 3A library | libcamera 3A | 無 / 有限 | 3A + Holoscan | 各有實現 |
| AWB 色溫範圍 | 2300-10000K | 2500-7500K | 有限 | 2000-12000K | 全光譜 → Thor |
| CCM 可調 | ✅ 3×3 矩陣 | ✅ tuning file | ❌ | ✅ + AI | 校正 → Orin |
| AWB 穩定性 | 良好 | 良好 | 差 | 最佳 | 室外 → Orin/Thor |
| 校正工具 | NVIDIA tuning | libcamera 向導 | 無 | NVIDIA + Holoscan | 各有工具 |
| 多光源支援 | ✅ 混合光源 | ✅ 混合光源 | 有限 | ✅ + AI 識別 | 複雜光源 → Thor |
| AWB 學習曲線 | 中高 | 中 | 低 | 高 | 入門 → RPi5 |