正規化的兩難:你應該將 RGB 除以 255 還是 256?

在編寫影像處理軟體時,第一個障礙之一就是將 8 位元整數顏色值 (0–255) 轉換為用於計算的浮點數。雖然這看起來微不足道,但在開發者之間存在著微妙的爭論:你應該透過除以 255.0 來進行正規化,還是應該使用帶有偏差的 256.0 除法?

這個選擇會影響你的演算法如何感知「黑色」與「白色」,如何處理捨入,以及如何與其他軟體產生的影像互動。了解這兩種方法的數學含義對於維持色彩精確度並確保相容性至關重要。

兩種方法

為了說明這個問題,請考慮將 8 位元整數轉換為浮點數及其反向轉換的兩種常見方法:

**標準方法 (除以 255) **

  • 轉換為浮點數: pixels = img / 255.0
  • 轉換為整數: output = np.trunc(result * 255 + 0.5)

**替代方法 (除以 256) **

  • 轉換為浮點數: pixels = (img + 0.5) / 256.0
  • 轉換為整數: output = np.trunc(result * 256)

在兩種情況下,最終輸出通常會被限制在 [0, 255] 範圍內,並轉回為無符號 8 位元整數 (uint8)。

標準方法的優點

標準方法是業界預設值,被 GPU 和大多數影像處理函式庫所使用。其主要優點在於語義上的清晰度:整數值 0 會精確地映射到 0.0(絕對黑色),而 255 會精確地映射到 1.0(絕對白色)。

對於大多數開發者來說,這是唯一邏輯性的選擇。如果你的處理邏輯需要偵測黑色像素或執行其中 0.0 代表空訊號的算術運算,標準方法允許你這樣做,而無需知道輸入影像的精確位元深度。

「半箱體」問題

標準方法的批評者指出了一個視覺化問題:當將浮點數轉回整數時,極端箱體 (0 和 255) 的寬度實際上只有內部箱體的一半。如果你在 0.0 到 1.0 之間生成均勻的隨機雜訊,並使用標準公式進行捨入,0 和 255 出現的頻率將會是任何其他整數的一半。

然而,在實際的影像處理中,這很少成為問題。因為原始影像已經過量化,往返轉換 (uint8floatuint8) 仍然是無損的。任何在處理過程中稍微超出 [0, 1] 範圍的值,仍會被限制在正確的極端箱體中,從而平衡分佈。

替代方法的優點

替代方法將轉換視為均勻的純量量化器。透過加上 0.5 的偏差並除以 256,每個整數都會被映射到其對應浮點數範圍的正中心。

理論精確度

從訊號處理的角度來看,替代方法是一種「中點踏步」量化器 (mid-tread quantizer)。從理論上來說,這減少了平均絕對重建誤差。如果你同時控制影像的儲存與讀取,你可以榨取出一點點額外的精確度。

抖動與雜訊

有些人認為替代方法簡化了抖動 (dithering)。因為每個值都位於中心,因此在整個範圍內對訊號添加雜訊會更加一致,避免了標準公式中需要透過仔細限制來保持雜訊分佈均勻的「尷尬極端值」問題。

技術對比與現實世界的限制

雖然數學上的爭論很有趣,但社群強調了幾個經常覆蓋這些理論疑慮的實際現實:

1. 相容性與「陌生人」問題

如果你正在處理由使用者或其他軟體提供的影像,你必須使用 255 除數。大多數在野外的影像都是使用標準公式量化的。使用 256 比例因子進行解碼會引入系統性的偏移與縮放誤差,實際上是在以比預期稍小的範圍進行影像處理。

2. 硬體現實

正如某些開發者所指出的,這些差異在處理硬體層級的訊號時變得至關重要。例如,當透過微控制器產生 VGA 訊號時,整數到電壓層級的映射是絕對的性的。如果不同的顏色通道使用不同的位元深度 (例如,藍色使用 3 位元,紅色使用 8 位元),正規化中的錯位可能會導致無法達成純灰色,從而產生肉眼可見的藍色或黃色色調。

3. 色彩空間的角色

有些人認為,整個爭論的次要地位於色彩空間的選擇。無論你使用 255 還是 256,其重要性都不如你是否在線性 RGB 或伽瑪校正後的空間 (例如 sRGB) 中工作。特定格式的 光學-電子轉換函數 (OETF) 與 電子-光學轉換函數 (EOTF) 對整數值的定義,遠比除數本身更具決定性。

結論:你應該使用哪一個?

對於絕大多數的應用程式,請使用 255 正規化。它保留了 0.0 與 1.0 的語義意義,確保了與影像生態系統其餘部分的相容性,

僅在以下情況考慮替代方法 (除以 256) 時:

  1. 你控制整個流程 (同時儲存與讀取)。
  2. 你不需要 0.0 代表絕對黑色。
    1. 你正在進行高精確度訊號處理,其中中點踏步量化誤差是可衡量的關注點。

除此之外,將誤差引入他人產生的影像中——以及這對其他開發者造成的困惑——其風險遠大於理論精確度的微小增益。

Sources