1. 程式人生 > 其它 >keras學習筆記-黑白照片自動著色的神經網路-Alpha版

keras學習筆記-黑白照片自動著色的神經網路-Alpha版

如今,上色都是人手工用Photoshop做的,一張圖片要花好幾個月才能完成,需要進行大量調查研究,光是其中的一張臉就需要多達20層圖層。但是,基於深度神經網路的自動著色機器人,可以幾秒鐘就實現PS幾個月的效果,而且成效越來越驚人。

下面,我們將分三個步驟展示如何打造你自己的著色神經網路。第一部分講解核心邏輯。我們將構建一個40行程式碼的神經網路,作為“Alpha”著色機器人,這個程式碼片段實際上沒有太多的魔法,但可以讓你熟悉基本操作。

然後,我們將建立一個可以泛化的神經網路——“Beta”版本。Beta機器人能對以前沒有看到的影象著色。

最後,我們將神經網路與一個分類器相結合,得到“最終”版本。我們將使用120萬張影象訓練過的Inception Resnet V2。為了讓著色效果吸引眼球,我們將使用Unsplash(免費相簿,裡面的圖片非常有藝術感和設計感)的人像作為資料,訓練我們的神經網路。

核心技術拆解:自動著色=發現灰度與彩色間的特徵

1、黑白影象可以在畫素網格中表示。每個畫素具有對應於其亮度的值,範圍為0 - 255,從黑色到白色。

2、彩色影象由三層組成:紅色層,綠色層和藍色層。直觀地,你可能會認為植物只存在於綠色層。但是,如下圖所示,綠色的葉子在三個通道中都有。這些層不僅可以確定顏色,還可以確定亮度。

為了得到白色這個顏色,需要將所有顏色均勻分佈。通過新增等量的紅色和藍色,綠色會變得更亮。因此,彩色影象使用三層對顏色和對比度進行編碼

就像黑白影象一樣,彩色影象中每個圖層的值也都為0 - 255。值為0意味著該圖層中沒有顏色。 如果所有顏色通道的值都為0,則影象畫素為黑色。

神經網路會建立輸入值和輸出值之間的關係。更準確地說,著色任務實際上就是網路需要找到連結灰度影象與彩色影象的特徵。

因此,著色機器人要尋找的,就是將灰度值網格連結到三色網格的特徵。

01

Alpha版本:40行程式碼,實現基礎著色機器人

我們從簡單的神經網路開始,給一張女性臉部影象(見下)著色。

只需40行程式碼,我們就能實現以下轉換。中間的影象是用神經網路完成的,右邊的圖片是原始的彩色照片。當然,這裡的網路使用了相同的影象做訓練和測試,稍後我們將在Beta版本中再來講這一點。

顏色空間

首先,我們使用一種演算法來改變顏色通道,從RGB到Lab。L表示亮度,a和b分別表示顏色光譜,綠-紅和藍-黃。

如下所示,Lab編碼的影象有一層灰度,將三層顏色層壓成兩層。這意味著我們可以在最終預測中使用原始的灰度影象。 此外,我們只有兩個通道做預測。

人類眼睛中有94%的細胞是確定亮度的,這是個科學事實。只有6%的受體被用作顏色的感測器。如上圖所示,灰度影象比彩色層更加清晰。這也是我們最終預測中保持灰度影象的另一個原因。

從黑白到彩色

我們的最終預測是這樣的。我們有一個輸入灰度層,我們想預測Lab中的兩個彩色層。要建立最終的彩色影象,我們將納入用於輸入的L/灰度影象,從而建立一個Lab影象。

我們使用卷積濾波器將一層轉成兩層。你可以將它們視為3D眼鏡中的藍/紅濾鏡。每個濾波器確定我們在圖片中看到的內容,可以突出顯示或刪除某些東西,從圖片中提取資訊。網路可以從濾波器中建立新的影象,也可以將多個濾波器組合成一個影象。

卷積神經網路的每個濾波器都自動調整,以幫助預期的結果。我們從堆疊數百個濾鏡開始,然後將它們縮小為兩層,即a層和b層。

下面是FloydHub程式碼:

from keras.layers import Conv2D, UpSampling2D, InputLayer, Conv2DTranspose
from keras.layers import Activation, Dense, Dropout, Flatten
from keras.layers.normalization import BatchNormalization
from keras.models import Sequential
from keras.preprocessing.image 
import ImageDataGenerator, array_to_img, img_to_array, load_img
from skimage.color import rgb2lab, lab2rgb, rgb2gray, xyz2lab
from skimage.io import imsave
import numpy as np
import os
import random
import tensorflow as tf
Using TensorFlow backend.# Get 
imagesimage = img_to_array(load_img('woman.jpg')) image = np.array(image, dtype=float)  X = rgb2lab(1.0/255*image)[:,:,0] Y = rgb2lab(1.0/255*image)[:,:,1:] Y /= 128X = X.reshape(1, 400, 400, 1) Y = Y.reshape(1, 400, 400, 2)# Building the neural networkmodel = Sequential() model.add(InputLayer(input_shape=(None, None, 1))) model.add(Conv2D(8, (3, 3), activation='relu', padding='same', strides=2)) model.add(Conv2D(8, (3, 3), activation='relu', padding='same')) model.add(Conv2D(16, (3, 3), activation='relu', padding='same')) model.add(Conv2D(16, (3, 3), activation='relu', padding='same', strides=2)) model.add(Conv2D(32, (3, 3), activation='relu', padding='same')) model.add(Conv2D(32, (3, 3), activation='relu', padding='same', strides=2)) model.add(UpSampling2D((2, 2))) model.add(Conv2D(32, (3, 3), activation='relu', padding='same')) model.add(UpSampling2D((2, 2))) model.add(Conv2D(16, (3, 3), activation='relu', padding='same')) model.add(UpSampling2D((2, 2))) model.add(Conv2D(2, (3, 3), activation='tanh', padding='same'))# Finish modelmodel.compile(optimizer='rmsprop', loss='mse')  model.fit(x=X, y=Y, batch_size=1, epochs=1000)
Epoch 1/1000
1/1 [==============================] - 1s - loss: 0.0286 Epoch 2/1000 1/1 [==============================] - 0s - loss: 0.0238  Epoch 318/1000 1/1 [==============================] - 0s - loss: 0.0010 Epoch 319/1000 1/1 [==============================] - 0s - loss: 7.4259e-04  Epoch 590/1000 1/1 [==============================] - 0s - loss: 5.5838e-04 Epoch 591/1000 1/1 [==============================] - 0s - loss: 4.7110e-04 Epoch 592/1000   Epoch 845/1000 1/1 [==============================] - 0s - loss: 3.5430e-04 Epoch 846/1000 1/1 [==============================] - 0s - loss: 2.9861e-04  1/1 [==============================] - 0s - loss: 3.0116e-04 Epoch 996/1000 1/1 [==============================] - 0s - loss: 3.1555e-04 Epoch 997/1000 1/1 [==============================] - 0s - loss: 3.0418e-04 Epoch 998/1000 1/1 [==============================] - 0s - loss: 4.3305e-04 Epoch 999/1000 1/1 [==============================] - 0s - loss: 3.9781e-04 Epoch 1000/1000 1/1 [==============================] - 0s - loss: 5.8701e-04<keras.callbacks.History at 0x11ccb6860>
print(model.evaluate(X, Y, batch_size=1)) output = model.predict(X) output *= 128# Output colorizationscur = np.zeros((400, 400, 3)) cur[:,:,0] = X[0][:,:,0] cur[:,:,1:] = output[0] imsave("img_result.png", lab2rgb(cur)) imsave("img_gray_version.png", rgb2gray(lab2rgb(cur)))
1/1 [==============================] - 0s 0.000459772680188 /usr/local/lib/python3.6/site-packages/skimage/util/dtype.py:122: UserWarning: Possible precision loss when converting from float64 to uint8 
.format(dtypeobj_in, dtypeobj_out))
/usr/local/lib/python3.6/site-packages/skimage/util/dtype.py:122: UserWarning: Possible precision loss when converting from float64 to uint16   .format(dtypeobj_in, dtypeobj_out))
# 視覺化資料集
import matplotlib.pyplot as plt %matplotlib inline   plt.rcParams['font.sans-serif']=['SimHei'] #用來正常顯示中文標籤
img = lab2rgb(cur) title = '黑白照片自動著色的神經網路-Alpha版'plt.imshow(img) plt.title(title)
plt.show()

output_7_0.png

Alpha版本不能很好地給未經訓練的影象著色。接下來,我們將在Beta版本中做到這一點——將上面的將神經網路泛化。