我們知道,深度學(xué)習(xí)幾乎已經(jīng)應(yīng)用在每一個領(lǐng)域,但如果我們能夠構(gòu)建一個基于深度學(xué)習(xí)的模型,讓它能夠給老照片著色,重現(xiàn)我們童年的舊回憶,這該多么令人激動??!那么我們要怎么做呢?本文的作者將為大家介紹一個教程,通過深度學(xué)習(xí)方法為黑白老照片自動上色,帶我們重新憶起那段老時(shí)光!
現(xiàn)如今,給照片著色通常是在 PS 中手工完成的。
所以說,如果要給一幅照片著色的話,短時(shí)間內(nèi)是不可能完成的。它需要廣泛的研究,要知道,單是一張臉的著色,就需要多達(dá)20層粉色、綠色和藍(lán)色的色調(diào)才能使照片擁有恰到好處的效果。
現(xiàn)在,我要介紹的這個簡單的神經(jīng)網(wǎng)絡(luò)——Inception Resnet V2,已經(jīng)訓(xùn)練了120萬張圖像,可以幫助我們完成著色的任務(wù)。為了能夠?qū)崿F(xiàn)著色,我們將用 Unsplash 的肖像來訓(xùn)練這個神經(jīng)網(wǎng)絡(luò)。
介紹
在本節(jié)中,我將就如何渲染圖像、數(shù)字顏色的基礎(chǔ)知識以及神經(jīng)網(wǎng)絡(luò)的主要邏輯進(jìn)行概述。
黑白圖像可以用像素網(wǎng)格表示,每個像素都有與其亮度相對應(yīng)的值。這些值的范圍是0~255,對應(yīng)的是從黑到白。
彩色圖像是由三層組成:紅色層、綠色層和藍(lán)色層。你可以想象一下,在白色背景上將綠葉分成三個通道。直覺上,你可能會認(rèn)為植物只存在于綠色層中。
但是,如下圖所示,葉子在所有三個通道中都存在。這些層不僅決定了顏色,還決定了亮度。
例如,要得到白色,你需要所有的顏色均勻分布。通過增加等量的紅色和藍(lán)色,會使綠色變得更亮。因此,彩色圖像使用三層來對顏色和對比度進(jìn)行編碼:
和黑白圖像一樣,彩色圖像中的每一層,也有0~255的值。值0表示這個層中沒有顏色。如果像素網(wǎng)格所有顏色通道的值都為0,那么這個圖像像素就是黑色的。
神經(jīng)網(wǎng)絡(luò)在輸入值和輸出值之間創(chuàng)建了一種關(guān)系。為了能夠更為準(zhǔn)確地完成著色任務(wù),網(wǎng)絡(luò)需要找到能夠?qū)⒒叶葓D像和彩色圖像聯(lián)系起來的特征。
總的來說就是,我們需要找到能夠?qū)⒒叶戎稻W(wǎng)格鏈接到三個顏色網(wǎng)格的特征。
f()是神經(jīng)網(wǎng)絡(luò),[B&W]是我們的輸入,[R]、[G]、[B]是我們的輸出
現(xiàn)在,隨著數(shù)據(jù)集的增加,由于我們處理的是高分辨率圖像,因此我們需要更多的計(jì)算能力。為此,我個人更喜歡使用 Deep Cognition 的 Deep Learning Studio jupyter notebooks,它為Amazon 的深度學(xué)習(xí)示例提供了GPU,可用來訓(xùn)練模型。
如果你不熟悉如何使用Deep Learning Studio,可以看看以下這些資料:
Deep Learning made easy with Deep Learning Studio?—?An Introduction
http://u6.gg/eqfdu
Deep Learning made easy with Deep Learning Studio?—?Complete Guide
http://u6.gg/eqffa
A video walkthrough of Deep Cognition
http://u6.gg/eqfh7
python代碼和數(shù)據(jù)集可以從 GitHub 中下載:
https://github.com/Rajat2712/Deep-Learning-Studio
環(huán)境設(shè)置
Deep Learning Studio 最好的地方之一就是,只需單擊 Deep Learning Studio Cloud,就可以輕松地完成安裝,然后隨時(shí)隨地使用它們。
▌1.安裝 Python 環(huán)境
要安裝 Python 環(huán)境,請點(diǎn)擊 DLS 中的 Environments 選項(xiàng)卡。
然后在 Available Environments 單擊你要安裝的環(huán)境。
對于這項(xiàng)任務(wù),我們將安裝以下環(huán)境:
Tensorflow-gpu-1.6.0
Keras-gpu-2.1.5
▌2.安裝python包
單擊啟動環(huán)境。然后點(diǎn)擊菜單的 Open New Terminal 打開終端。
在終端中鍵入以下命令:
1pipinstallscikit-image
上傳數(shù)據(jù)集
打開文件瀏覽器,并為這個項(xiàng)目創(chuàng)建一個新文件夾。上傳在 Github 存儲庫中可用的數(shù)據(jù)集。
如果需要自定義數(shù)據(jù)集,可以通過在 train 文件夾中上傳高分辨率的彩色圖像和test文件夾中的灰度圖像來創(chuàng)建。
接下來我們開始編碼
▌導(dǎo)入所有的庫
1importkeras 2fromkeras.applications.inception_resnet_v2importInceptionResNetV2 3fromkeras.preprocessingimportimage 4fromkeras.engineimportLayer 5fromkeras.applications.inception_resnet_v2importpreprocess_input 6fromkeras.layersimportConv2D,UpSampling2D,InputLayer,Conv2DTranspose,Input,Reshape,merge,concatenate 7fromkeras.layersimportActivation,Dense,Dropout,Flatten 8fromkeras.layers.normalizationimportBatchNormalization 9fromkeras.callbacksimportTensorBoard10fromkeras.modelsimportSequential,Model11fromkeras.layers.coreimportRepeatVector,Permute12fromkeras.preprocessing.imageimportImageDataGenerator,array_to_img,img_to_array,load_img13fromskimage.colorimportrgb2lab,lab2rgb,rgb2gray,gray2rgb14fromskimage.transformimportresize15fromskimage.ioimportimsave16importnumpyasnp17importos18importrandom19importtensorflowastf
▌從Train文件夾中讀取所有圖像并加載初始權(quán)重值
1#Getimages2X=[]3forfilenameinos.listdir('Train/'):4X.append(img_to_array(load_img('Train/'+filename)))5X=np.array(X,dtype=float)6Xtrain=1.0/255*X7#Loadweights8inception=InceptionResNetV2(weights='imagenet',include_top=True)9inception.graph=tf.get_default_graph()
▌在融合層(fusion layer)兩邊分別創(chuàng)建編碼器和解碼器
Inception ResNet v2 是一個在120萬張圖像上訓(xùn)練的神經(jīng)網(wǎng)絡(luò),也是現(xiàn)今最強(qiáng)大的分類器之一。與編碼器并行,輸入圖像也通過 Inception ResNet v2 來運(yùn)行。提取分類層并將其與編碼器的輸出合并。
通過將學(xué)習(xí)從分類轉(zhuǎn)移到著色網(wǎng)絡(luò)上,網(wǎng)絡(luò)可以對圖片中的內(nèi)容有所了解。進(jìn)而使網(wǎng)絡(luò)能夠?qū)⒅桨概c對象表示相匹配。
將encoder_input輸入到我們的編碼器模型中,然后將編碼器模型的輸出與融合層中的 embed_input融合,用融合層的輸出作為解碼器模型的輸入,最后返回最終的輸出decoder_output。
1embed_input=Input(shape=(1000,)) 2#Encoder 3encoder_input=Input(shape=(256,256,1,)) 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#Fusion13fusion_output=RepeatVector(32*32)(embed_input)14fusion_output=Reshape(([32,32,1000]))(fusion_output)15fusion_output=concatenate([encoder_output,fusion_output],axis=3)16fusion_output=Conv2D(256,(1,1),activation='relu',padding='same')(fusion_output)17#Decoder18decoder_output=Conv2D(128,(3,3),activation='relu',padding='same')(fusion_output)19decoder_output=UpSampling2D((2,2))(decoder_output)20decoder_output=Conv2D(64,(3,3),activation='relu',padding='same')(decoder_output)21decoder_output=UpSampling2D((2,2))(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,(3,3),activation='tanh',padding='same')(decoder_output)25decoder_output=UpSampling2D((2,2))(decoder_output)26model=Model(inputs=[encoder_input,embed_input],outputs=decoder_output)
現(xiàn)在,我們必須調(diào)整圖像的大小來適應(yīng) Inception 模型。然后根據(jù)模型對像素和顏色值使用預(yù)處理器進(jìn)行格式化。在最后一步中,我們通過 Inception 網(wǎng)絡(luò)運(yùn)行它并提取模型的最后一層。
1defcreate_inception_embedding(grayscaled_rgb): 2grayscaled_rgb_resized=[] 3foriingrayscaled_rgb: 4i=resize(i,(299,299,3),mode='constant') 5grayscaled_rgb_resized.append(i) 6grayscaled_rgb_resized=np.array(grayscaled_rgb_resized) 7grayscaled_rgb_resized=preprocess_input(grayscaled_rgb_resized) 8withinception.graph.as_default(): 9embed=inception.predict(grayscaled_rgb_resized)10returnembed
用ImageDataGenertor可以調(diào)整圖像生成器的設(shè)置。如此一來得到不會重復(fù)的圖像,從而提高了學(xué)習(xí)率。shear_rangetilts使圖像向左或向右傾斜,其他設(shè)置為縮放、旋轉(zhuǎn)和水平翻轉(zhuǎn)。
1#Imagetransformer2datagen=ImageDataGenerator(3shear_range=0.2,4zoom_range=0.2,5rotation_range=20,6horizontal_flip=True)7#Generatetrainingdata8batch_size=10
我們使用 Xtrain 文件夾中的圖像,根據(jù)上面的設(shè)置生成圖像。然后,為X_batch提取黑色層和白色層,并為兩個顏色層提取兩種顏色。
為創(chuàng)建我們的 batch,我們使用經(jīng)過調(diào)整的圖像。將它們轉(zhuǎn)換為黑白圖像,并通過 Inception ResNet 模型運(yùn)行它們。
1defimage_a_b_gen(batch_size):2forbatchindatagen.flow(Xtrain,batch_size=batch_size):3grayscaled_rgb=gray2rgb(rgb2gray(batch))4embed=create_inception_embedding(grayscaled_rgb)5lab_batch=rgb2lab(batch)6X_batch=lab_batch[:,:,:,0]7X_batch=X_batch.reshape(X_batch.shape+(1,))8Y_batch=lab_batch[:,:,:,1:]/1289yield([X_batch,create_inception_embedding(grayscaled_rgb)],Y_batch)
現(xiàn)在,我們將使用 “RMSProp” 優(yōu)化器和均方誤差作為損失函數(shù)來編譯模型。
GPU 越強(qiáng),得到的圖像就越多。通過現(xiàn)在的設(shè)置,你可以使用50~100張圖像。steps_per_epoch是通過將訓(xùn)練圖像的數(shù)量除以 batch 大小來計(jì)算的。
1#Trainmodel2model.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 顏色空間,這意味著我們?yōu)槊總€顏色通道使用 0 ~ 255 之間的數(shù)字。這將會產(chǎn)生 1670 萬種顏色的組合。
而人類只能感知 200 ~ 1000 萬種顏色,因此,使用再大的顏色空間并沒有多大意義。
與 RGB 顏色空間相比,LAB 顏色空間具有不同的范圍。在 LAB 顏色空間中,顏色光譜 ab 范圍從-128~128。通過將輸出層中的所有值除以 128,將色譜范圍限制在 -1 ~ 1 之間。
將它與神經(jīng)網(wǎng)絡(luò)相匹配,神經(jīng)網(wǎng)絡(luò)也返回 -1 ~ 1 之間的值。
在使用 rgb2lab 函數(shù)轉(zhuǎn)換顏色空間之后,我們選擇灰度層:[:,:,0],這是對神經(jīng)網(wǎng)絡(luò)的輸入。[:,:,1:]選擇兩個顏色層:綠-紅和藍(lán)-黃。
1color_me=[]2forfilenameinos.listdir('Test/'):3color_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,))
神經(jīng)網(wǎng)絡(luò)進(jìn)行訓(xùn)練后,做出最終的預(yù)測,并將其轉(zhuǎn)化為圖像。
在這里,我們使用一個灰度圖像作為輸入,并通過訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)來運(yùn)行它。我們?nèi)≡?-1 ~ 1 之間所有的輸出值,然后乘以 128,就得到了 Lab 色譜中正確的顏色。
最后,用 三層 0 填充得到一個黑色的 RGB 畫布。然后從測試圖像中,復(fù)制灰度圖層。然后將這兩個顏色層添加到 RGB 畫布上。再將這個像素值數(shù)組轉(zhuǎn)換為圖片。
1#Testmodel2output=model.predict([color_me,color_me_embed])3output=output*1284#Outputcolorizations5foriinrange(len(output)):6cur=np.zeros((256,256,3))7cur[:,:,0]=color_me[i][:,:,0]8cur[:,:,1:]=output[i]9imsave("result/img_"+str(i)+".png",lab2rgb(cur))
結(jié)果
在小型數(shù)據(jù)集上的結(jié)果,訓(xùn)練圖像數(shù) = 10,測試圖像數(shù) = 8;
▌測試數(shù)據(jù):
▌經(jīng)過50個輪數(shù)之后:
▌經(jīng)過100個輪數(shù)之后:
▌經(jīng)過1000個輪數(shù)之后:
▌經(jīng)過2000個輪數(shù)之后:
-
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4772瀏覽量
100806 -
圖像
+關(guān)注
關(guān)注
2文章
1085瀏覽量
40479 -
深度學(xué)習(xí)
+關(guān)注
關(guān)注
73文章
5503瀏覽量
121206
原文標(biāo)題:用AI給黑白照片上色,復(fù)現(xiàn)記憶中的舊時(shí)光
文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論