單元 8 · RAW 擷取與資料格式

RAW、bayer、HSB 資料

RAW 與處理後格式

格式說明
NV12 / YUVISP 處理後
SRGGB10 / Bayer RAW感測器原始(調校分析)

HSB 的資料形式

HSB 把感測器資料封包走乙太網路,host 端解包可選 RAW 或處理後。RAW 分析仍是品質調校基礎。

陷阱:Bayer order 設錯 → 全色錯。走 HSB 時,感測器端與 host 端格式要一致。

8.6 RAW 擷取實作(本平台)

argus / Holoscan 取 RAW
argus_camera / Holoscan 取 RAW

RAW 是影像品質分析的根本:雜訊、黑位、Bayer order 都回 RAW。

8.7 常見 RAW 格式錯誤

錯誤症狀檢查
Bayer order 錯色彩全亂拍純色卡判別四通道
bit depth 錯讀暗部階調斷裂確認 RAW 位元深
packing 錯條紋狀假影用對應位元深工具解析

8.8 多模式一致性(調校前必修)

重要:不同解析度/ binning 下 Bayer order 與 shading 不同。調校與回歸必須鎖定單一模式(固定 size + format)。

8.9 深入原理:RAW10 的 packing 位元級

感測器輸出 10-bit 像素,但儲存/傳輸常包成 RAW10(4 bytes 裝 5 pixels)節省頻寬。解析 RAW 前必須先 unpack,否則像素值全錯。

RAW10 packing(MIPI 4-byte / 5-pixel)
5 個 10-bit 像素 = 50 bits
pack 成 4 bytes(32 bits):前 8 個 pixel[7:0] 高位,
再放 2 個「整組 extra」bit 集合
# 以 Python 讀取:raw10 bytes → 像素 array
def unpack_raw10(buf):
    out = []
    for i in range(0, len(buf), 5):
        b0,b1,b2,b3,b4 = buf[i:i+5]
        out.append((b0<<2) | (b4>>0 & 0x03))
        out.append((b1<<2) | (b4>>2 & 0x03))
        out.append((b2<<2) | (b4>>4 & 0x03))
        out.append((b3<<2) | (b4>>6 & 0x03))
        out.append(b4>>... )  # 依 MIPI 規範實作
    return out
陷阱:用錯 packing(把 10-bit 當 16-bit 或 8-bit 讀)→ 畫面呈現「條紋狀假影」或色帶。解 RAW 一律用與 sensor mode 相符的 unpack 函式,且先驗證:讀回黑位應是固定常數。

8.10 Worked Example:從 RAW 檔驗證 Bayer order 與黑位

分析 RAW 前三步
python3 - <<'EOF'
import rawpy, numpy as np
raw = rawpy.imread('frame.dng').raw_image
print(raw.shape)                # (H, W),1 channel(Bayer)
bl = raw[0:20, 0:20].mean()     # 黑框區應接近黑位
print('black level ~', bl)
b = raw[::2, ::2]; g1 = raw[::2, 1::2]
g2 = raw[1::2, ::2]; r = raw[1::2, 1::2]
print('R/Gr/Gb/B means:', r.mean(), g1.mean(), g2.mean(), b.mean())
EOF
判讀:拍純白時 R≈G≈B;拍灰卡時四通道比例應固定。若 Gr≠Gb → Bayer order 錯(unit-02 曾提)。黑位若飄移 → 感測器 OB/暗電流問題。

8.11 疑難排解決策樹:RAW 顯示異常

「RAW 看起來不對」
1. 有彩色條紋?
   ├─ packing 錯(unit-08 陷阱)
   └─ 或 Bayer order 錯
2. 全圖偏某一色?
   └─ Bayer order 判別(拍白卡)
3. 有固定直條紋?
   └─ 位元深/packing 錯、或 stride 算錯
4. 有亮點/黑點?
   └─ 缺陷像素(unit-13 DPC)
5. 曝光不對?
   └─ 回 unit-10 曝光控制

8.12 常見錯誤與陷阱

陷阱 1:stride/pitch 沒算——每列結尾可能 padding(如對齊到 8/16 bytes)。用 rows×cols×bytes 假設算 offset 會錯位。
陷阱 2:RAW 位元深搞混——10-bit sensor 用 10-bit 讀出,即使存成 16-bit,內容仍是 0–1023。直接當 16-bit 用會把有效範圍誤判。
陷阱 3:HSB 端 RAW 有「封包 header」混入——走乙太網路時,解包需先剝離封包 metadata,否則第一列會多出幾 byte 造成錯位。

8.13 練習

  1. 取一張 RAW 並寫 unpack 驗證黑位。
  2. 拍白卡確認 Bayer order。
  3. 故意用錯位元深讀一次,記下「條紋」的特徵,練出辨識力。

8.14 深入原理:MIPI CSI-2、stride 與有效像素

解析 RAW 時要把三個概念分開:有效像素是感測器真正輸出的 W×H,payload 是 packing 後的位元組,stride/pitch 則是 buffer 每列實際跳過的距離。MIPI packet 的 word count 只描述 payload,不一定等於 driver buffer 的 pitch;DMA 對齊也可能在每列尾端加入 padding。

層級要回答的問題驗證
CSI packetDT、word count、ECC/CRC 是否正確?dmesg、CSI counter
buffer layout每列從哪個 byte 開始?bytesperline、plane length
pixel decode每 10/12 bit 如何還原?灰階分布、黑位、白位
判斷原則:若第一列正常、每列逐漸錯位,先查 stride;若每五個像素重複出現條紋,先查 RAW10 packing;若整張圖顏色一致地錯,才查 Bayer order。

8.15 Worked Example:從 CSI 位元數到檔案大小

1280×800 RAW10 的三個答案
有效像素:1280 × 800 = 1,024,000 pixels

這個例子說明「檔案大小正確」仍不代表畫面正確:若讀檔程式忽略 64 bytes padding,第二列起就會斜移。先從 V4L2 query 回讀 bytesperlinesizeimage,再決定 decoder 的 row stride。

8.16 疑難排解決策樹:RAW 條紋從哪一層來

逐層縮小範圍
1. CSI/HSB 有 CRC、drop 或 sequence error?
   ├─ 有 → 先查 lane rate、線材、封包/網路統計
   └─ 無 ─┐
2. 每列起點是否依 bytesperline 前進?
   ├─ 否 → 修 stride/pitch 與 plane offset
   └─ 是 ─┐
3. 5-pixel/4-byte(或 sensor 指定)邊界出現規律條紋?
   ├─ 是 → 修 RAW packing / bit shift
   └─ 否 ─┐
4. 白卡四通道是否只是顏色順序錯?
   ├─ 是 → 修 Bayer order
   └─ 否 → 查曝光、黑位、DPC 與 ISP

8.17 常見錯誤與陷阱

陷阱 1:把 CSI bit rate 當成檔案 bytes。CSI 還有 packet/header、lane 分配與對齊;頻寬估算與 buffer layout 必須分開。
陷阱 2:忽略有效位元所在 bit。有些 10-bit 16-bit container 左移 6 bit,有些右對齊;直接轉成 uint16 會讓亮度差 64 倍。
陷阱 3:用 ISP 後的 YUV 判斷 RAW。YUV 已經過黑位、demosaic、gamma;格式問題要回到 RAW 或未處理 capture 驗證。

8.18 練習

  1. 讀出平台的 bytesperlinesizeimage、fourcc,寫下三者關係。
  2. 用同一幀資料分別套用正確與錯誤 stride,描述兩者的視覺特徵。
  3. 用白卡與黑框各做一次 Bayer、packing、黑位檢查,將結果存入回歸紀錄。
看完這單元你應該能說出:
  • RAW vs NV12 用途。
  • HSB 資料封包的 RAW 分析。
  • Bayer order 陷阱。
  • RAW 在調校分析角色。

延伸閱讀

8.19 進階真實情境 Worked Example:HSB 路徑的 RAW 解包完整性驗證

場景:Thor T5000 透過 HSB 接 OV9281(1280×800 RAW10 @ 120 fps),Holoscan 解包後取 RAW。取到的 RAW 有規律的彩色條紋,但同一顆感測器走 CSI 直接取流時正常。

HSB RAW 解包分析
# 問題定位:
# CSI 直取 RAW 正常 → 感測器輸出正確
# HSB 取 RAW 有條紋 → 解包/封包層問題

# 分析步驟:
1. 比較 CSI 與 HSB 兩路 RAW 的前 10 bytes
   → HSB 多了 4 bytes 的 packet header
   → 原始解包未剝離 header → 第一列像素錯位 4 bytes

2. 驗證 stride:
   CSI:bytesperline = 1280 × 10/8 = 1600
   HSB:bytesperline = 1600 + 4(header)= 1604
   # 若用 CSI 的 stride 讀 HSB 的 RAW → 每列累積錯位

3. 修正方案:
   # 在 Holoscan SensorSourceOp 中設定 header_offset = 4
   # 或用 V4L2 的 V4L2_BUF_DATA_FORMAT 設定 header size

# 設計決策:
# 1. HSB 與 CSI 的 RAW 格式差異在封包 header——內容相同、包裝不同
# 2. 解包時必須先剝離 header,再用 sensor mode 的 stride 進行解析
# 3. 標準做法:用 V4L2 query 回讀 bytesperline,而非自行假設
設計決策:HSB 與 CSI 的 RAW 差異「只在封包層」但「後果在像素層」。解法是永遠從 driver/device query 回讀 stride 和 header size,而不是假設「感測器 mode 相同就一切相同」。

8.20 深入原理擴充:RAW12 packing 與多感測器的 stride 互斥

RAW10 是 4 bytes 裝 5 pixels,RAW12 則是 3 bytes 裝 2 pixels(或 2 bytes 裝 1 pixel + padding)。在多感測器系統中,若 4 顆感測器使用不同的 RAW bit depth(例如前視 RAW12 + 側視 RAW10),每路的 stride 與 packing 規則不同,Holoscan 的 buffer pool 必須為每路維護獨立的 unpack 設定。

容易忽略的邊界案例:若 Holoscan 的 buffer pool 誤用 RAW12 的 unpack 函式去解 RAW10 資料,解出來的像素值會有 2-bit 的系統性偏移(最大可達 3 倍亮度差)。這種錯誤在灰卡上不明顯(因為亮度均勻),但在色彩豐富的場景會產生不可預期的色帶。務必為每路感測器指定正確的 unpack 設定。

8.21 診斷式疑難排解表

症狀可能原因解決方案
RAW 第一列正常、第二列起逐漸錯位stride/pitch 設定不包含 padding bytes回讀 V4L2 的 bytesperline,確保 decoder 使用正確的 row stride
HSB RAW 有 5-pixel 為一組的規律條紋RAW10 packing 未正確解包確認 unpack 函式符合 MIPI CSI-2 的 RAW10 packing 規範;驗證黑位應為固定常數
同一感測器 CSI 取 RAW 正常但 HSB 取 RAW 有彩色條紋HSB 封包 header 未剝離在 Holoscan SensorSourceOp 設定 header_offset;或用 V4L2 query 回讀
RAW 位元深搞混(10-bit 當 16-bit 讀)導致亮度差 64 倍container 大小 vs 有效位元所在 bit 未確認確認有效位元在 container 的哪個 bit(左移 6 bit 或右對齊);用黑位值驗證
多感測器中某路的 RAW packing 設定被其他路覆蓋Holoscan buffer pool 未為每路維護獨立設定為每路感測器建立獨立的 unpack 設定;避免共用全域 buffer pool 設定

8.22 進階挑戰題

  1. 設計一個 RAW 完整性自動化測試腳本:對同一 sensor mode 分別用 CSI 與 HSB 取 RAW,自動比較前 100 bytes、stride、header size 與黑位值,輸出差異報告。
  2. 若你的專案需要同時處理 RAW10(2 顆 OV9281)與 RAW12(1 顆 OV5640),設計一個 Holoscan buffer pool 架構:每路的 unpack 設定如何管理?pool 總大小如何計算?
  3. 從 CSI bit rate、packet header、lane 分配與 DMA 對齊四個層級,分別解釋「raw bitrate 正確」仍可能導致 RAW 條紋的所有可能原因。

8.23 專案級端到端 Worked Example:RAW 工具鏈建立專案 — 解包、驗證、自動化

場景:調校團隊需要一套「可重複使用的 RAW 分析工具鏈」,支援多感測器(RAW10/RAW12 混用)、CSI 與 HSB 雙路徑。

里程碑規劃
M1 單張解包
   ├─ 寫 unpack_raw10 / unpack_raw12 函式
   ├─ 用已知黑位驗證
   └─ 通過:黑位 = 固定常數

M2 stride 處理
   ├─ 從 V4L2 query 回讀 bytesperline/sizeimage
   ├─ decoder 依 bytesperline 前進
   └─ 通過:多列連續無錯位

M3 雙路徑支援
   ├─ CSI 與 HSB 各建載入器
   ├─ HSB 剝離 packet header
   └─ 通過:兩路 RAW 內容一致

M4 自動化檢查
   ├─ Bayer order / 黑位 / histogram 自動輸出
   └─ 通過:一鍵產出 RAW 健康報告

M5 多感測器
   ├─ 每路獨立 unpack 設定
   └─ 通過:RAW10/RAW12 混用各自正確

M6 整合 repo
   └─ 通過:工具鏈 + 測試檔 + README 進 repo
專案要點:RAW 工具鏈是「調校的顯微鏡」。一次投資,之後每個單元(黑位、雜訊、LSC、AWB)都靠它。最重要的一行:bytesperline 永遠從 device query 回讀,不要假設

8.24 量測 / 驗證 SOP:RAW 完整性驗證

RAW SOP(Step 1–6)
Step 1 查 layout
   v4l2-ctl -d /dev/video0 --get-fmt-video
   # 記錄 bytesperline、sizeimage、fourcc
Step 2 取 RAW
   v4l2-ctl -d /dev/video0 --set-fmt-video=pixelformat=SRGGB10 --stream-mmap=3 --stream-count=1 --stream-to=r.raw
Step 3 檔案大小
   ls -l r.raw   # ≈ W×H×10/8(±padding)
Step 4 解包驗證
   python 解包 → 檢查黑位(固定常數)
Step 5 Bayer order
   拍白卡,四通道平均,Gr≈Gb
Step 6 HSB 對照(若有)
   剝 header 後與 CSI 的 RAW 比較

判讀指標:
  條紋規律 → packing/stride 錯
  全圖偏色 → Bayer order 錯
  黑位飄移 → 感測器/解包錯

8.25 平台間對照:RAW 擷取與格式

面向Thor T5000RPi5Orange PiOrin Nano
RAW fourccSRGGB10/12(V4L2)rpicam --raw(DNG)V4L2 RAWSRGGB10/12(V4L2)
RAW 容器raw bufferDNG(含 metadata)raw bufferraw buffer
bytesperline 取得V4L2 querylibcamera metadataV4L2 queryV4L2 query
HSB 封包 header✅ 需剝離
RAW10 packingMIPI 4B/5P同 MIPI(DNG 解包)同 MIPI同 MIPI
選擇思考:RAW 的位元層規則(MIPI packing、stride)跨平台一致。RPi5 的 DNG 容器最方便(附 metadata),Thor/Orin 的 raw buffer 最裸(要自己解)——但都是同一顆感測器的同一份資料。

8.26 互動式檢核清單

  • - [ ] 我能說出 RAW10 的 4-byte/5-pixel packing 規則並解包。
  • - [ ] 我能從 V4L2 query 讀出 bytesperline 與 sizeimage。
  • - [ ] 我能用白卡驗證 Bayer order、用黑框驗證黑位。
  • - [ ] 我能處理 HSB 的封包 header(剝離後再解析)。
  • - [ ] 我能管理 RAW10/RAW12 混用的多路 unpack 設定。
  • - [ ] 我能區分「packing 錯」「stride 錯」「Bayer 錯」三種症狀。

8.18 Register 位元級完整工作流

本單元涉及的關鍵 register,以及「讀→改→寫→驗證」的完整位元級操作序列:

Register位址功能Bit Field 說明
CSI_PIXEL_FORMAT0x0c0a0008CSI 像素格式設定bit[5:0]=DT (0x2B=RAW10, 0x2C=RAW12, 0x1E=YUV422)
VI_FORMAT0x0c800008VI 輸入格式bit[5:0]=format code, bit[9:8]=BPP
讀→改→寫→驗證 完整序列(以 CSI_PIXEL_FORMAT 為例)
# Step 1: 讀取目前值
$ devmem2 0x0c0a0008 w
# 記錄 current_value

# Step 2: 計算新值(設定 bit[0]=1)
$ new_value=$((current_value | 0x0001))

# Step 3: 寫入
$ devmem2 0x0c0a0008 w $new_value

# Step 4: 驗證
$ devmem2 0x0c0a0008 w
# 確認 bit[0] = 1,其餘 bit 不變

# Step 5: 進階 — bitmask 操作
$ read_val=$(devmem2 0x0c0a0008 w | grep "Read" | awk '{print $NF}')
$ mask=0x0001
$ expected=0x0001
$ [ $(($read_val & $mask)) -eq $expected ] && echo "PASS" || echo "FAIL: bit[0] not set"

8.19 多層疑難排解決策樹

決策樹 1:RAW 資料解析異常
1. 用 hexdump 看 raw 檔,data 看起來隨機?
   ├─ 格式不對 → 確認 DT 設的 data type(0x2B=RAW10, 0x2C=RAW12)
   └─ 資料對但 display 畸形 → 解析度設定不符(stride 不對)
2. frame 間有 shift?
   ├─ sensor line length 不符 → 檢查 sensor datasheet 的 line_length
   └─ V4L2 bytesperline 設錯 → 修改 format callback
決策樹 2:HSB vs CSI RAW 資料不一致
1. HSB stream 的 raw 與 CSI raw 格式不同?
   ├─ HSB 封包有額外 header → 用 Holoscan 的 packet parser
   └─ byte order 不同(little vs big endian)→ 設定 swap

8.20 量測驗證完整 SOP

RAW 資料驗證完整 SOP:

步驟動作指令/方法預期輸出
Step 1確定格式`v4l2-ctl -d /dev/video0 --list-formats-ext`確認 RAW10/12
Step 2抓一幀 raw`v4l2-ctl --stream-mmap --stream-count=1 --stream-to=frame.raw`檔案大小 = W×H×BPP
Step 3驗證 header`xxd frame.raw | head`DT byte = 0x2B (RAW10) 或 0x2C (RAW12)
Step 4驗證解析度file 大小 / (W×H×BPP) 應 = 1(±0.1%)stride 正確
Step 5Bayer pattern 確認裁切 2×2 block 看 R/Gr/Gb/B 分佈Bayer order 正確
Step 6連續幀穩定抓 10 幀比較 hash相同(固定場景)

8.21 四平台終極對照

面向Thor T5000RPi5Orange PiOrin Nano
支援 RAW 格式RAW8–16, YUV, PDAFRAW10, YUVRAW10, YUVRAW10–14, YUV
RAW 傳輸方式MIPI CSI-2 + HSBMIPI CSI-2MIPI CSI-2MIPI CSI-2 + GMSL
BPP 處理硬體 unpack(CSI→ISP)軟體 unpack軟體 unpack硬體 unpack
HSB 封包格式Ethernet frame + headerN/AN/AN/A
PDAF 資料分離
Frame metadata 支援

8.22 完整 Bring-up 小 Checklist

針對「RAW 擷取與資料格式」主題的完整 bring-up 步驟清單:

  • - [ ] 我能手動解析 raw 檔的 MIPI packet header,確認 data type。
  • - [ ] 我能驗證 raw 檔大小是否符合 W×H×BPP。
  • - [ ] 我能區分 HSB 封包格式與 CSI raw 格式的差異。
  • - [ ] 我能比較四平台的 RAW 格式支援範圍。
這是 NVIDIA Jetson Thor T5000 感測器影像調適繁中教學站 · 由 OpenCode 建置
本站教學內容(繁體中文解說)為本站原創,採 CC-BY-4.0;規格與指令引用自 NVIDIA Jetson Thor 官方頁NVIDIA Holoscan 與公開感測器資料。