1. 程式人生 > >用AI給黑白照片上色,復現記憶中的舊時光

用AI給黑白照片上色,復現記憶中的舊時光

AI技術年度盛會即將開啟!11月8-9日,來自Google、Amazon、微軟、Facebook、LinkedIn、阿里巴巴、百度、騰訊、美團、京東、小米、位元組跳動、滴滴、商湯、曠視、思必馳、第四正規化、雲知聲等企業的技術大咖將帶來工業界AI應用的最新思維。

如果你是某個AI技術領域的專業人才,或想尋求將AI技術整合至傳統企業業務當中,點選填寫,我們將從中挑選出20名相關性最高的幸運讀者,送出單場分論壇入場券。

此外,如果你想與所有參會大牛充分交流溝通,點選閱讀原文購票,使用優惠碼:AI2018-DBY 購買兩日通票,立減999元;此外大會還推出了1024定製票,主會+分會自由組合,精彩隨心。大會嘉賓陣容和議題,請檢視文末海報

作者 | Rajat

譯者 | 婉清

編輯 | Jane

出品 | AI科技大本營

【導讀】我們知道,深度學習幾乎已經應用在每一個領域,但如果我們能夠構建一個基於深度學習的模型,讓它能夠給老照片著色,重現我們童年的舊回憶,這該多麼令人激動啊!那麼我們要怎麼做呢?本文的作者將為大家介紹一個教程,通過深度學習方法為黑白老照片自動上色,帶我們重新憶起那段老時光!

雖然現在人人討論AI,但我認為普惠AI還離我們很遠,原因有三:
1. AI技術的易用性、價效比、安全性都有待考量和實驗
2. AI難落地,雲雖然是AI的載體,但現在的雲廠商所能提供的AI能力非常有限
3. 開發者自身難轉型,難適應的問題
基於此,我認為對於現階段的雲廠商還有一些生存空間,但毋庸置疑,AI+雲服務才是未來雲廠商大浪淘金,不被淘汰的唯一法寶。


今天,我給大家分享一個我的AI實踐。

640?wx_fmt=jpeg

現如今,給照片著色通常是在 PS 中手工完成的。如果想知道這個著色的過程背後的工作有多麼不容易,來看看下面一段視訊就知道了:

所以說,如果要給一幅照片著色的話,短時間內是不可能完成的。它需要廣泛的研究,要知道,單是一張臉的著色,就需要多達20層粉色、綠色和藍色的色調才能使照片擁有恰到好處的效果。

現在,我要介紹的這個簡單的神經網路——Inception Resnet V2,已經訓練了120萬張影象,可以幫助我們完成著色的任務。為了能夠實現著色,我們將用 Unsplash 的肖像來訓練這個神經網路。

介紹

在本節中,我將就如何渲染影象、數字顏色的基礎知識以及神經網路的主要邏輯進行概述。

黑白影象可以用畫素網格表示,每個畫素都有與其亮度相對應的值。這些值的範圍是0~255,對應的是從黑到白。

640?wx_fmt=jpeg



彩色影象是由三層組成:紅色層、綠色層和藍色層。你可以想象一下,在白色背景上將綠葉分成三個通道。直覺上,你可能會認為植物只存在於綠色層中。

但是,如下圖所示,葉子在所有三個通道中都存在。這些層不僅決定了顏色,還決定了亮度。

640?wx_fmt=jpeg



例如,要得到白色,你需要所有的顏色均勻分佈。通過增加等量的紅色和藍色,會使綠色變得更亮。因此,彩色影象使用三層來對顏色和對比度進行編碼:

640?wx_fmt=png

和黑白影象一樣,彩色影象中的每一層,也有0~255的值。值0表示這個層中沒有顏色。如果畫素網格所有顏色通道的值都為0,那麼這個影象畫素就是黑色的。

神經網路在輸入值和輸出值之間建立了一種關係。為了能夠更為準確地完成著色任務,網路需要找到能夠將灰度影象和彩色影象聯絡起來的特徵。

總的來說就是,我們需要找到能夠將灰度值網格連結到三個顏色網格的特徵。

640?wx_fmt=png

f()是神經網路,[B&W]是我們的輸入,[R]、[G]、[B]是我們的輸出

現在,隨著資料集的增加,由於我們處理的是高解析度影象,因此我們需要更多的計算能力。為此,我個人更喜歡使用 Deep Cognition 的 Deep Learning Studio jupyter notebooks,它為Amazon 的深度學習示例提供了GPU,可用來訓練模型。

如果你不熟悉如何使用Deep Learning Studio,可以看看以下這些資料:

環境設定

Deep Learning Studio 最好的地方之一就是,只需單擊 Deep Learning Studio Cloud,就可以輕鬆地完成安裝,然後隨時隨地使用它們。

1.安裝 Python 環境

要安裝 Python 環境,請點選 DLS 中的 Environments 選項卡。

640?wx_fmt=png

640?wx_fmt=png

然後在 Available Environments 單擊你要安裝的環境。

640?wx_fmt=png

640?wx_fmt=png

對於這項任務,我們將安裝以下環境:

  • Python3

  • Tensorflow-gpu-1.6.0

  • Keras-gpu-2.1.5

640?wx_fmt=png

2.安裝python包

單擊啟動環境。然後點選選單的 Open New Terminal 開啟終端。

640?wx_fmt=png

在終端中鍵入以下命令:

1pip install scikit-image

640?wx_fmt=png

上傳資料集

開啟檔案瀏覽器,併為這個專案建立一個新資料夾。上傳在 Github 儲存庫中可用的資料集。

如果需要自定義資料集,可以通過在 train 資料夾中上傳高解析度的彩色影象和test資料夾中的灰度影象來建立。

接下來開始編碼

匯入所有的庫

 1import keras
 2from keras.applications.inception_resnet_v2 import InceptionResNetV2
 3from keras.preprocessing import image
 4from keras.engine import Layer
 5from keras.applications.inception_resnet_v2 import preprocess_input
 6from keras.layers import Conv2D, UpSampling2D, InputLayer, Conv2DTranspose, Input, Reshape, merge, concatenate
 7from keras.layers import Activation, Dense, Dropout, Flatten
 8from keras.layers.normalization import BatchNormalization
 9from keras.callbacks import TensorBoard 
10from keras.models import Sequential, Model
11from keras.layers.core import RepeatVector, Permute
12from keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img
13from skimage.color import rgb2lab, lab2rgb, rgb2gray, gray2rgb
14from skimage.transform import resize
15from skimage.io import imsave
16import numpy as np
17import os
18import random
19import tensorflow as tf

從Train資料夾中讀取所有影象並載入初始權重值

1# Get images
2X = []
3for filename in os.listdir('Train/'):
4    X.append(img_to_array(load_img('Train/'+filename)))
5X = np.array(X, dtype=float)
6Xtrain = 1.0/255*X
7#Load weights
8inception = InceptionResNetV2(weights='imagenet', include_top=True)
9inception.graph = tf.get_default_graph()

融合層(fusion layer)兩邊分別建立編碼器和解碼器

Inception ResNet v2 是一個在120萬張影象上訓練的神經網路,也是現今最強大的分類器之一。與編碼器並行,輸入影象也通過 Inception ResNet v2 來執行。提取分類層並將其與編碼器的輸出合併。

通過將學習從分類轉移到著色網路上,網路可以對圖片中的內容有所瞭解。進而使網路能夠將著色方案與物件表示相匹配。

將 encoder_input 輸入到我們的編碼器模型中,然後將編碼器模型的輸出與融合層中的  embed_input 融合,用融合層的輸出作為解碼器模型的輸入,最後返回最終的輸出 decoder_output

 1embed_input = Input(shape=(1000,))
 2#Encoder
 3encoder_input = Input(shape=(2562561,))
 4encoder_output = Conv2D(64, (3,3), activation='relu', padding='same', strides=2)(encoder_input)
 5encoder_output = Conv2D(128, (3,3), activation='relu', padding='same')(encoder_output)
 6encoder_output = Conv2D(128, (3,3), activation='relu', padding='same', strides=2)(encoder_output)
 7encoder_output = Conv2D(256, (3,3), activation='relu', padding='same')(encoder_output)
 8encoder_output = Conv2D(256, (3,3), activation='relu', padding='same', strides=2)(encoder_output)
 9encoder_output = Conv2D(512, (3,3), activation='relu', padding='same')(encoder_output)
10encoder_output = Conv2D(512, (3,3), activation='relu', padding='same')(encoder_output)
11encoder_output = Conv2D(256, (3,3), activation='relu', padding='same')(encoder_output)
12#Fusion
13fusion_output = RepeatVector(32 * 32)(embed_input) 
14fusion_output = Reshape(([32321000]))(fusion_output)
15fusion_output = concatenate([encoder_output, fusion_output], axis=316fusion_output = Conv2D(256, (11), activation='relu', padding='same')(fusion_output)
17#Decoder
18decoder_output = Conv2D(128, (3,3), activation='relu', padding='same')(fusion_output)
19decoder_output = UpSampling2D((22))(decoder_output)
20decoder_output = Conv2D(64, (3,3), activation='relu', padding='same')(decoder_output)
21decoder_output = UpSampling2D((22))(decoder_output)
22decoder_output = Conv2D(32, (3,3), activation='relu', padding='same')(decoder_output)
23decoder_output = Conv2D(16, (3,3), activation='relu', padding='same')(decoder_output)
24decoder_output = Conv2D(2, (33), activation='tanh', padding='same')(decoder_output)
25decoder_output = UpSampling2D((22))(decoder_output)
26model = Model(inputs=[encoder_input, embed_input], outputs=decoder_output)

現在,我們必須調整影象的大小來適應 Inception 模型。然後根據模型對畫素和顏色值使用前處理器進行格式化。在最後一步中,我們通過 Inception 網路執行它並提取模型的最後一層。

 1def create_inception_embedding(grayscaled_rgb):
 2    grayscaled_rgb_resized = []
 3    for i in grayscaled_rgb:
 4        i = resize(i, (2992993), mode='constant')
 5        grayscaled_rgb_resized.append(i)
 6    grayscaled_rgb_resized = np.array(grayscaled_rgb_resized)
 7    grayscaled_rgb_resized = preprocess_input(grayscaled_rgb_resized)
 8    with inception.graph.as_default():
 9        embed = inception.predict(grayscaled_rgb_resized)
10    return embed

用 ImageDataGenertor 可以調整影象生成器的設定。如此一來得到不會重複的影象,從而提高了學習率。shear_rangetilts 使影象向左或向右傾斜,其他設定為縮放、旋轉和水平翻轉。

1# Image transformer
2datagen = ImageDataGenerator(
3        shear_range=0.2,
4        zoom_range=0.2,
5        rotation_range=20,
6        horizontal_flip=True)
7#Generate training data
8batch_size = 10

我們使用 Xtrain 資料夾中的影象,根據上面的設定生成影象。然後,為 X_batch 提取黑色層和白色層,併為兩個顏色層提取兩種顏色。

為建立我們的 batch,我們使用經過調整的影象。將它們轉換為黑白影象,並通過 Inception ResNet 模型執行它們。

1def image_a_b_gen(batch_size):
2    for batch in datagen.flow(Xtrain, batch_size=batch_size):
3        grayscaled_rgb = gray2rgb(rgb2gray(batch))
4        embed = create_inception_embedding(grayscaled_rgb)
5        lab_batch = rgb2lab(batch)
6        X_batch = lab_batch[:,:,:,0]
7        X_batch = X_batch.reshape(X_batch.shape+(1,))
8        Y_batch = lab_batch[:,:,:,1:] / 128
9        yield ([X_batch, create_inception_embedding(grayscaled_rgb)], Y_batch)

現在,我們將使用 “RMSProp” 優化器和均方誤差作為損失函式來編譯模型。

GPU 越強,得到的影象就越多。通過現在的設定,你可以使用50~100張影象。steps_per_epoch 是通過將訓練影象的數量除以 batch 大小來計算的。

1#Train model      
2model.compile(optimizer='rmsprop', loss='mse')
3model.fit_generator(image_a_b_gen(batch_size), epochs=50, steps_per_epoch=1)

1.0/255 表示我們使用的是 24 位 RGB 顏色空間,這意味著我們為每個顏色通道使用 0 ~ 255 之間的數字。這將會產生 1670 萬種顏色的組合。

而人類只能感知 200 ~ 1000 萬種顏色,因此,使用再大的顏色空間並沒有多大意義。

與 RGB 顏色空間相比,LAB 顏色空間具有不同的範圍。在 LAB 顏色空間中,顏色光譜 ab 範圍從-128~128。通過將輸出層中的所有值除以 128,將色譜範圍限制在 -1 ~ 1 之間。

將它與神經網路相匹配,神經網路也返回 -1 ~ 1 之間的值。

在使用 rgb2lab 函式轉換顏色空間之後,我們選擇灰度層:[:,:,0],這是對神經網路的輸入。[:,:,1:] 選擇兩個顏色層:綠-紅和藍-黃。

1color_me = []
2for filename in os.listdir('Test/'):
3    color_me.append(img_to_array(load_img('Test/'+filename)))
4color_me = np.array(color_me, dtype=float)
5gray_me = gray2rgb(rgb2gray(1.0/255*color_me))
6color_me_embed = create_inception_embedding(gray_me)
7color_me = rgb2lab(1.0/255*color_me)[:,:,:,0]
8color_me = color_me+.reshape(color_me.shape+(1,))

神經網路進行訓練後,做出最終的預測,並將其轉化為影象。

在這裡,我們使用一個灰度影象作為輸入,並通過訓練好的神經網路來執行它。我們取在 -1 ~ 1 之間所有的輸出值,然後乘以 128,就得到了 Lab 色譜中正確的顏色。

最後,用 三層 0 填充得到一個黑色的 RGB 畫布。然後從測試影象中,複製灰度圖層。然後將這兩個顏色層新增到 RGB 畫布上。再將這個畫素值陣列轉換為圖片。

1# Test model
2output = model.predict([color_me, color_me_embed])
3output = output * 128
4# Output colorizations
5for i in range(len(output)):
6    cur = np.zeros((2562563))
7    cur[:,:,0] = color_me[i][:,:,0]
8    cur[:,:,1:] = output[i]
9    imsave("result/img_"+str(i)+".png", lab2rgb(cur))

結果

在小型資料集上的結果,訓練影象數 = 10,測試影象數 = 8;

測試資料:

640?wx_fmt=png



經過50個輪數之後:

640?wx_fmt=png

經過100個輪數之後:

640?wx_fmt=png

經過1000個輪數之後:

640?wx_fmt=png

經過2000個輪數之後:

640?wx_fmt=png

原文連結

—【完】—

2018 AI開發者大會

只講技術,拒絕空談

2018 AI開發者大會是一場由中美人工智慧技術高手聯袂打造的AI技術與產業的年度盛會!是一場以技術落地為導向的乾貨會議!大會設定了10場技術專題論壇,力邀15+矽谷實力講師團和80+AI領軍企業技術核心人物,多位一線經驗大咖帶你將AI從雲端落地。

大會日程以及嘉賓議題請檢視下方海報(點選檢視大圖)