4.17. 感測器調節旋鈕

除了 pixformat()framesize() 之外,CSI 類別還公開了少數幾項針對個別感測器的控制項,幾乎每個應用程式遲早都會用到它們——包括安裝方向、曝光、增益、白平衡,以及幾個除錯輔助功能。每一項都直接對應到先前介紹過的感測器概念;該 API 只是為驅動程式底層所做的暫存器寫入提供一個 Python 操作介面。

以下所有方法都作用於底層的感測器。它們全都透過感測器的 I2C 控制匯流排 推送暫存器寫入,因此成本僅為數微秒,而新設定會在 下一次 曝光時生效——通常就是下一次的 snapshot()

4.17.1. 方向

相機並不知道自己被安裝成哪個方向。在感測器端套用的兩個翻轉旗標,可以在任何像素離開晶片之前就把畫面轉到正確的方向::

csi0.hmirror(True)
csi0.vflip(True)

hmirror() 進行左右翻轉,vflip() 進行上下翻轉。兩者搭配可涵蓋實務上會遇到的情況:以倒置方式安裝的電路板(兩個旗標都設為 True)、置於正面鍍銀鏡子後方的電路板(僅 hmirror),或從下方觀看反射場景的情況(僅 vflip)。

由於翻轉發生在感測器的讀出邏輯中,因此沒有 CPU 成本,也沒有記憶體額外開銷——影格落入影格緩衝區時就已經是正確方向了。

4.17.2. 曝光

曝光指的是積分時間——也就是每個像素中的光電二極體在該列被讀出之前收集電荷的時間長度,以微秒為單位。驅動程式啟動時,感測器的自動曝光迴圈是運作中的,因此相機會嘗試將平均像素值維持在某個目標附近。停用該迴圈會把曝光固定在應用程式所選定的值::

csi0.auto_exposure(False, exposure_us=8000)

當場景亮度穩定、且應用程式需要可預測的運動模糊或需要逐格一致的強度以進行閾值處理時,固定曝光就是正確的選擇。讀回目前的曝光值——無論它是由迴圈設定還是由應用程式設定——則是另一個獨立的呼叫::

us = csi0.exposure_us()

True 且不帶曝光值的方式呼叫 auto_exposure(),會把控制權交還給迴圈。

4.17.3. 增益

增益是在像素電壓抵達 ADC 之前對其施加的放大量,以分貝為單位。與曝光一樣,驅動程式啟動時自動增益迴圈是開啟的。常見的有兩種模式。設定上限可讓迴圈適應光照,同時又阻止它在昏暗場景中無限制地放大雜訊::

csi0.auto_gain(True, gain_db_ceiling=16)

當應用程式也固定曝光時,固定增益就是正確的做法——對於需要逐格比較像素值的應用程式(例如色彩追蹤)而言,增益的穩定性非常重要::

csi0.auto_gain(False, gain_db=0)

目前的增益可透過 gain_db() 讀回。每當應用程式停用自動增益時,也應該同時停用自動白平衡與自動曝光——否則仍在運作中的控制迴圈會以各種方式擾動影像,使固定增益失去意義。

4.17.4. 白平衡

白平衡是 ISP 對來自去拜耳階段的紅、綠、藍三個通道所施加的逐通道增益,使白色物體在任何色光下看起來都是白色的。自動白平衡迴圈會根據 ISP 在每一影格上收集的逐區域 統計資料 計算出這三個增益,並於下一影格套用。

大多數應用程式會讓此迴圈持續運作。色彩追蹤是常見的例外——這些增益正是迴圈為了追逐有色物體而會去調整的對象,因此若應用程式正試圖尋找紅色色塊,迴圈會悄悄地把紅色通道調暗,導致該色塊不再符合條件。鎖定該迴圈即可解決這個問題::

csi0.auto_whitebal(False)

傳入以分貝表示的明確 (r, g, b) 元組,可進行可重現的色彩校正——在不同電路板與不同工作階段間都使用相同的增益::

csi0.auto_whitebal(False, rgb_gain_db=(0.0, 0.0, 0.0))

目前的增益可透過 rgb_gain_db() 以元組形式讀回。

4.17.5. 影格率上限

感測器預設以其原生影格率運作——大多數零件為每秒 30 到 60 影格,而高速感測器在影格尺寸夠小時可達到高得多的數值。設定上限可讓應用程式將相機節流到下游處理所能跟得上的速率::

csi0.framerate(15)

在支援硬體速率控制的感測器上,此呼叫也會延長每影格的曝光預算,這在低光環境下會有幫助;在其他感測器上,驅動程式則只是在影格緩衝區層級略過多餘的影格。

4.17.6. 測試圖案

彩色條測試圖案內建於大多數感測器中,對於將 成像 問題與 輸出 問題分離開來非常有用。開啟它會繞過光電二極體陣列,並沿著相同的像素資料路徑送出一個固定圖案::

csi0.colorbar(True)

如果測試圖案看起來正常但即時影像不正常,那麼故障就出在光學系統或感測器的類比前端;如果連測試圖案本身都損毀了,問題就出在像素資料匯流排的某處,或出在 pixformat() / framesize() 的設定上。傳入 False 即可回到即時影像。

完整的 API 請參閱 csi.CSI,其中包括針對個別感測器的 ioctl() 命令,這些命令可公開特定感測器系列所獨有的控制項。