5.19. 色調校正

色調校正會改變所擷取影像中亮度與色彩的分佈方式 -- 也就是當一張影格太暗、太亮、太平淡,或偏向錯誤色彩時,應用程式所套用的修正。

這些校正分為兩大類:重新分配亮度的亮度與對比調整,以及改變每個像素所呈現色彩的色彩調整。兩者在感測器的 ISP 中都有對應功能,會在影格進入時即時加以校正;而這裡介紹的方法則是事後套用在已擷取的 Image 上,適用於影格需要比 ISP 所提供更多校正的情況。

5.19.1. 直方圖均衡化

最簡單的對比拉伸運算是 直方圖均衡化(histogram equalisation)。其概念是重新映射像素值,使輸出的直方圖盡可能平坦 -- 每個值出現的頻率大致相同。視覺上的效果是:低對比影像(其直方圖集中於狹窄區間)會變成高對比影像,像素涵蓋完整的 0 -- 255 範圍。

histeq() 會執行均衡化:

img.histeq()

其運作方式很直接。先計算來源直方圖的累積分佈函數(CDF);每個輸入像素值會被映射到它在 CDF 中的位置,並縮放到輸出範圍。原本就分佈均勻的像素,其映射接近恆等變換;原本堆積在某個亮度的像素,則透過將該亮度拉伸到更廣的輸出值範圍而被分散開來。

在低對比場景上效果極為顯著 -- 一張昏暗的室內照片與經過 histeq 處理後的同一張照片之間的差異,往往就是「無法辨識」與「清晰可讀」之間的差別。其代價是該運算會放大 所有東西,包括感測器雜訊。對於確實有低對比細節需要還原的場景,histeq 是正確的選擇;但對於曝光良好、本就不需要它的乾淨場景,histeq 會引入可見的雜訊。

5.19.2. CLAHE:自適應均衡化

直方圖均衡化是全域性的:它使用一個從整張影像計算出的 CDF,並套用到所有地方。這對亮度範圍大致均勻的影像有效,但在具有局部暗區與亮區的場景上會失效 -- CDF 會被像素較多的一側拉偏,而另一側則會被過度校正。

其自適應變體是 對比受限自適應直方圖均衡化(Contrast Limited Adaptive Histogram Equalisation),通常稱為 CLAHE。CLAHE 不使用單一的 全域 CDF,而是為影像的每個小區塊計算各自的 CDF,針對各區塊以其自身的 CDF 進行均衡化,再將區塊邊界融合在一起。結果是亮度調整以 局部 方式進行 -- 陰影中的角落會得到屬於自己的均衡化,而不會被明亮的角落往錯誤方向拉動。

adaptive=True 旗標會將 histeq() 切換為 CLAHE 模式:

img.histeq(adaptive=True, clip_limit=10)

clip_limit 參數正是 CLAHE 名稱中「對比受限」所指的部分。局部均衡化在 CDF 只有極少不同數值的平坦區域中可能會過度放大雜訊;裁切限制會限定任一單一區間可被重新分配的強度上限,從而避免雜訊放大,同時仍允許在需要之處進行對比拉伸。10 左右的值是合理的起點;較大的值會讓 CLAHE 運作得更積極,但代價是更明顯的雜訊,較小的值則使其更溫和。

CLAHE 比 全域 histeq 更耗費資源,但在亮度分佈不均的場景上會產生更乾淨的結果 -- 而這正是大多數真實世界場景的情況。

5.19.3. Gamma、對比與亮度

直方圖均衡化是依資料驅動的方式來重新映射亮度。不依賴資料 的方式則是套用一條選定的曲線,並以幾個易於調整的旋鈕加以參數化。gamma() 提供三個:

img.gamma(gamma=1.0, contrast=1.0, brightness=0.0)

每個參數都會對每個像素套用一種特定的轉換:

gamma 會將每個像素值代入冪函數 output = input ** (1 / gamma)。其標準意義為:大於 1.0 的值會 提亮 影像並抬升中間色調(即經典的「螢幕 gamma」校正);小於 1.0 的值則會使其 變暗。此參數是非線性的 -- 它會保留黑點與白點,僅重塑兩者之間的分佈,這在目標是還原陰影或高光區域中的細節而不壓垮既有極值時,正是正確的行為。

contrast 會將每個像素圍繞中灰點進行直接的乘法運算。大於 1.0 的值會增加對比(暗的更暗、亮的更亮、中灰維持不變);小於 1.0 的值則會降低對比。

brightness 會為每個像素值加上一個常數。正值會提亮,負值會變暗。此偏移是 均勻 的 -- 不保留任何東西 -- 這本身很少是應用程式所想要的,但與對比處理搭配使用時,能很好地重新置中結果。

這三個參數可以組合運用:一次 gamma() 呼叫即可在單一處理流程中先套用 gamma 曲線、再進行對比乘法、最後做亮度偏移。其順序為 gamma 優先,接著是對比,最後是亮度,這個順序在三者都採用非預設值時能給出最直觀的結果。

5.19.4. 自動白平衡

色調校正中的色彩類別始於 自動白平衡。感測器的 ISP 在成像流程中所執行的相同機制 -- 調整紅、綠、藍通道的相對增益,使一塊平均為灰色的色塊呈現為實際的灰色 -- 也可作為事後處理運算套用在已完成的 Image 上:

img.awb()

預設使用 灰世界(gray-world) 演算法:假設整張影像的平均色彩為中性灰,並調整各通道增益使其成立。另一種 max=True 形式則使用 白塊(white-patch) 演算法:假設最亮的像素為中性白,並調整增益使其成立。兩者都適用於 RGB565 與原始 Bayer 格式;皆不適用於灰階(其中沒有色彩可供平衡)或 YUV(其色彩表示法並非這些演算法所運作的對象)。

何時應採用事後處理形式而非 ISP 的自動白平衡:當 ISP 的選擇不適合特定場景時、當應用程式從磁碟載入在不同條件下擷取的參考影格時,或當色彩判斷的重要性高到足以讓應用程式想以自己選定的演算法重新執行時。

5.19.5. 色彩校正矩陣

當影像所需的色彩校正不是白平衡所提供的逐通道縮放,而是更一般化的 通道混合 時,應採用的運算是 色彩校正矩陣ccm() 方法會套用一個 3×3(或含偏移的 3×4)矩陣,將每個像素的 (r, g, b) 向量相乘以產生新的 (r, g, b) 向量:

img.ccm([[1.1, -0.05, -0.05],
        [-0.05, 1.1, -0.05],
        [-0.05, -0.05, 1.1]])

此矩陣讓應用程式能校正色彩通道之間的串擾 -- 例如,當紅色感測器的響應包含了部分綠光時,矩陣可從紅色輸出中減去綠色通道的一部分以加以補償。結合逐通道偏移後,3×4 形式還能讓應用程式重新將每個通道歸零。

ISP 流程 的內容涵蓋了色彩校正矩陣的 原理Image 上的事後處理形式只是相同的運算,於事後套用而已。