為單色注入生命:探索深度學習圖像著色

舊照片的深褐色調和灰階漸層具有獨特的魅力,捕捉了凝固在時間中的瞬間。然而,它們往往缺乏原始場景生動的即時感。想像一下,將生命的色彩重新注入這些珍貴的記憶中,將一張褪色的黑白肖像轉變成一扇窗,展現出主體世界的全貌色彩。這個轉變過程,被稱為圖像著色,長期以來一直吸引著藝術家和歷史學家。如今,在人工智慧,特別是深度學習進步的推動下,自動著色正在取得曾經只存在於科幻小說中的成果。

為灰階圖像帶來色彩提出了一個引人入勝的挑戰。當圖像以單色呈現時,大量的資訊——原始的色彩數據——在本質上就遺失了。演算法如何可能僅憑亮度值就得知一朵花、一件衣服或天空的真實顏色?答案在於灰階圖像本身內嵌的細微線索:紋理、形狀、上下文以及光影的相互作用。雖然精確定位確切的原始顏色可能是不可能的(那朵玫瑰真的是深紅色,還是粉紅色?),目標轉變為創造一個貌似可信且在美學上令人信服的著色。其目的是產生一張人類觀察者會覺得可信,甚至可能無法與原始彩色照片區分的圖像。

深度學習模型擅長在龐大的數據集中揭示複雜的模式和統計關係。通過在數百萬張圖像上訓練這些模型,比較灰階版本與其原始彩色對應物,演算法學會將特定的紋理和結構與可能的顏色聯繫起來。它們學會了草通常是綠色的,天空通常是藍色的,以及某些紋理對應於木紋或織物。這類似於一種有根據的猜測,但這種猜測是基於一個巨大的視覺百科全書。演算法並不像人類那樣’知道’真實的顏色,但它可以根據學習到的相關性做出高度可能的預測。

色彩的語言:CIELab 與神經網路

為了以計算方式處理著色問題,我們需要一種合適的方式來表示顏色。雖然 RGB(紅、綠、藍)常用於顯示器,但它混合了亮度(brightness)和色度(chrominance)資訊。對於這項任務,一個更有利的系統是 CIELab 色彩空間。這個模型巧妙地將顏色分離成三個不同的組成部分:

  • L (Lightness): 這個通道代表灰階資訊,範圍從純黑到純白。它基本上就是我們在黑白圖像中已有的輸入數據。
  • a: 這個通道編碼了從綠色(負值)到紅色(正值)的光譜。
  • b: 這個通道編碼了從藍色(負值)到黃色(正值)的光譜。

CIELab 的優點在於這種分離。我們的深度學習模型可以專注於僅根據輸入的亮度(’L’)通道來預測兩個色度通道(’a’ 和 ‘b’)。核心任務變成了:給定灰階資訊(L),每個像素最可能對應的 ‘a’ 和 ‘b’ 值是什麼?

早期的嘗試通常採用卷積神經網路(Convolutional Neural Networks, CNNs)——一種特別擅長處理如圖像般的網格狀數據的深度學習架構。這些網路在大型圖像數據集(如 ImageNet)上進行訓練,直接預測每個像素的 ‘a’ 和 ‘b’ 值,將其視為一個回歸問題(預測連續值)。然而,一個常見的陷阱出現了:由此產生的著色結果常常顯得不飽和或黯淡。為什麼?考慮像蘋果這樣的物體。它可能合理地是紅色、綠色,甚至黃色。如果網路在回歸過程中試圖平均這些可能性,它可能會選擇一個沉悶、偏棕色的折衷方案,而不是一個鮮豔、特定的顏色。這種跨越多種可能顏色的平均效應傾向於沖淡結果。

範式轉移:將著色視為分類

為了克服不飽和問題並產生更鮮豔、更逼真的顏色,一種更複雜的方法重新定義了這個問題。它不再將顏色預測視為回歸,而是將其視為一個分類任務

以下是概念上的轉變:

  1. 量化色彩空間 (Quantized Color Space): 將可能的 ‘a’ 和 ‘b’ 值的連續光譜離散化為一組預先定義的代表性顏色’區間’或類別。可以把它想像成將一個巨大的調色板縮減為一組可管理但全面的、在 ‘a’-‘b’ 平面內的獨特色彩選項。
  2. 預測機率 (Predicting Probabilities): 對於輸入灰階圖像中的每個像素,CNN 不會預測單一的 ‘a’ 和 ‘b’ 值。相反,它會輸出一個跨越量化顏色區間的機率分佈。它基本上是說:’對於這個像素,有 70% 的機率屬於’鮮紅區間 #5’,20% 的機率是’淡紅區間 #2’,5% 的機率是’棕色區間 #12’’,依此類推。
  3. 處理模糊性 (Addressing Ambiguity): 這種機率方法內在地處理了顏色的模糊性。如果一個物體可能是多種顏色(如蘋果),網路可以為幾個不同的顏色區間分配顯著的機率,反映這種不確定性,而無需訴諸於平淡的平均值。
  4. 解碼為鮮豔色彩 (Decoding to Vibrant Color): 最後一步涉及將此機率分佈轉換回每個像素的單一、特定顏色。一種簡單的方法可能只是選擇具有最高機率的顏色區間(眾數)。然而,為了鼓勵鮮豔度並避免不飽和問題,使用了諸如計算分佈的退火平均值 (annealed mean) 等技術。這種方法給予機率較低但色彩更豐富(飽和度更高)的預測更多的權重,有效地在偏向鮮豔度的同時’打破僵局’,同時仍然尊重整體預測的分佈。

這種分類框架,結合專為著色設計的損失函數(用於在訓練期間評估模型性能的指標)的仔細設計,使模型能夠學習灰階特徵與可能顏色分佈之間的複雜關係。其結果是圖像不僅著色貌似可信,而且還具有早期基於回歸的方法通常缺乏的豐富性和視覺吸引力。

深入了解:實用的深度學習工作流程

雖然從頭開始訓練這樣一個複雜的 CNN 是一項艱鉅的任務,需要巨大的計算資源和龐大的數據集,但利用預訓練模型使這項技術變得觸手可及。讓我們逐步了解使用預訓練深度學習模型(特別是像原始範例中那樣使用 Caffe 框架構建的模型)進行圖像著色的概念步驟,並使用 Python 和常用函式庫實現。

1. 組合工具箱:

基礎通常涉及 Python,這是一種在數據科學和 AI 領域流行的多功能程式語言。關鍵函式庫扮演著重要角色:

  • NumPy: 對於高效的數值運算至關重要,特別是處理表示圖像的多維陣列。
  • OpenCV (cv2): 一個用於電腦視覺任務的強大函式庫。它提供讀取、寫入、操作和顯示圖像的功能,並且關鍵地包含一個深度神經網路(Deep Neural Network, DNN)模組,能夠加載和運行在 Caffe、TensorFlow 和 PyTorch 等各種框架中訓練的模型。
  • Argparse: 一個標準的 Python 函式庫,用於創建用戶友好的命令行介面,允許用戶輕鬆指定輸入參數,如圖像文件路徑。
  • OS: 用於基本的作業系統交互,例如以跨不同系統(Windows、macOS、Linux)工作的方式構建文件路徑。

2. 獲取預訓練智能:

我們不需從零開始構建神經網路,而是利用代表已為著色訓練好的網路的文件。這些通常包括:

  • 模型架構文件 (.prototxt for Caffe): 此文件定義了神經網路的結構——層、它們的類型、連接和參數。它是模型的藍圖。
  • 訓練好的權重文件 (.caffemodel for Caffe): 此文件包含網路在其廣泛訓練過程中學習到的數值權重。這些權重封裝了模型獲得的關於將灰階特徵映射到顏色機率的’知識’。它是提煉出的智能。
  • 顏色量化數據 (.npy file): 這個 NumPy 文件通常存儲前面描述的分類方法中使用的量化顏色區間的中心點。它充當預測顏色機率的參考調色板。

這些文件代表了可能在強大硬體上進行數週或數月訓練的結晶。

3. 加載著色引擎:

有了必要的文件,OpenCV 的 DNN 模組提供了將預訓練網路加載到記憶體中的機制。cv2.dnn.readNetFromCaffe 函數(或其他框架的等效函數)將架構和權重文件作為輸入,並實例化網路,使其準備好進行推論(inference,即對新數據進行預測的過程)。來自 .npy 文件的顏色量化點也通常使用 NumPy 加載。

4. 微調網路組件(如果需要):

有時,預訓練網路中的特定層在推論前需要進行微小的調整。在討論的基於分類的著色模型的背景下:

  • 輸出層調整: 負責輸出 ‘a’ 和 ‘b’ 通道預測的最終層(例如,在參考模型中命名為 class8_ab)可能需要從 .npy 文件中明確加載顏色區間中心點。這確保了網路的輸出機率正確映射到預定義的調色板。這些點通常在分配給層的 ‘blobs’(Caffe 對數據容器的術語)之前被重塑並轉換為適當的數據類型(例如,float32)。
  • 顏色重新平衡: 另一層(例如,conv8_313_rh)可能會被調整以影響輸出中不同顏色之間的平衡,可能增強飽和度或校正在訓練期間學到的偏差。這通常涉及將層的 blobs 設置為特定的學習值(如原始代碼中提到的 2.606 值,可能是在實驗中或訓練期間得出的)。

這些步驟使用分類方法,針對著色任務的特定細微差別,對通用的預訓練模型進行了調整。

5. 準備輸入圖像:

輸入的灰階圖像在饋送到神經網路之前需要經過幾個預處理步驟:

  • 加載: 使用 cv2.imread 從指定的文件路徑讀取圖像。即使是灰階圖像,OpenCV 默認情況下也可能將其加載為 3 通道的 BGR 圖像,將灰度值複製到所有通道。
  • 標準化 (Normalization): 像素值通常範圍從 0 到 255,通過除以 255.0 將其縮放到較小的範圍,通常是 0.0 到 1.0。這種標準化有助於穩定網路的學習和推論過程。
  • 色彩空間轉換: 使用 cv2.cvtColor 將圖像從默認的 BGR 色彩空間轉換為 CIELab 色彩空間。這對於隔離亮度(L)通道至關重要。
  • 調整大小 (Resizing): 大多數預訓練的 CNN 期望輸入圖像具有固定的大小(例如,224x224 像素,這是受 ImageNet 等數據集影響的常見標準)。使用 cv2.resize 相應地調整 LAB 圖像的大小。這種標準化確保了與網路架構的兼容性。
  • L 通道隔離和中心化: 從調整大小後的 LAB 圖像中提取亮度(L)通道。通常,其值(在 LAB 中通常為 0-100)通過減去平均值(例如 50)來使其圍繞零中心化。這種中心化是另一種可以提高網路性能的常見做法。

這個經過精心預處理的 L 通道現在已準備好呈現給網路。

6. 推論步驟:預測顏色:

這就是魔法發生的地方:

  • Blob 創建: 將處理後的 L 通道(現在是一個 2D 陣列)轉換為 DNN 模組期望的 ‘blob’,一個 4 維陣列格式 (cv2.dnn.blobFromImage)。此格式通常包括批次大小、通道數、高度和寬度的維度。
  • 前向傳播 (Forward Pass): 使用 net.setInput 將 blob 設置為加載網路的輸入。然後,調用 net.forward() 方法。這觸發了計算:輸入數據流經網路的各層,根據學習到的權重進行轉換,最終產生預測的輸出。對於我們的著色模型,輸出代表預測的 ‘a’ 和 ‘b’ 通道(或者更確切地說,是顏色區間上的機率分佈)。
  • 輸出重塑: 來自網路的原始輸出需要被重塑並轉置回對應於 ‘a’ 和 ‘b’ 通道的 2D 空間格式。

網路現在已經根據輸入的灰階圖像生成了其對顏色資訊的最佳猜測。

7. 重建彩色圖像:

最後階段涉及將預測的顏色資訊與原始圖像數據結合起來:

  • 調整預測通道大小: 預測的 ‘a’ 和 ‘b’ 通道(目前大小為 224x224,與網路輸入匹配)需要使用 cv2.resize 調整回輸入圖像的原始尺寸。這確保了顏色資訊與原始圖像結構正確對齊。
  • 提取原始亮度: 至關重要的是,從原始、全尺寸的 LAB 圖像(在預處理期間調整大小之前創建)中提取亮度(L)通道。使用原始 L 通道保留了圖像的原始細節和亮度結構,如果使用調整大小後的 L 通道,這些細節將會退化。
  • 串接 (Concatenation): 將原始 L 通道與調整大小後的、預測的 ‘a’ 和 ‘b’ 通道沿顏色通道軸合併(串接)。這重新組合成一個完整的 LAB 圖像,現在帶有預測的顏色。
  • 轉換回可顯示格式: 使用 cv2.cvtColor 將生成的 LAB 圖像轉換回 BGR 色彩空間,因為這是大多數圖像顯示函數(如 cv2.imshow)期望的標準格式。
  • 裁剪和縮放: BGR 圖像中的像素值,目前在標準化範圍內(可能為 0.0 到 1.0),被裁剪以確保它們保持在此有效範圍內(由於預測過程,值有時會略微超出邊界)。然後,它們被縮放回標準的 0-255 整數範圍,以便顯示或保存為標準圖像文件。

8. 可視化:

最後,可以使用像 cv2.imshow 這樣的函數來並排顯示原始灰階圖像及其新著色的對應物,以便進行即時的視覺比較。

執行過程:

通常,實現這些步驟的腳本會從命令行運行。使用 argparse 設置,用戶將提供輸入灰階圖像的路徑作為參數(例如,python colorize_image.py --image my_photo.jpg)。然後腳本執行加載、預處理、推論和重建步驟,最終顯示或保存著色結果。

這個工作流程利用預訓練模型和強大的函式庫,將深度學習著色的複雜理論轉化為一個實用工具,能夠為單色圖像添加生動、貌似可信的色彩,有效地彌合了過去與現在之間的鴻溝。