久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

想打造一個(gè)神經(jīng)網(wǎng)絡(luò),,自動(dòng)給黑白照片上色,?這兒有一份超詳細(xì)教程

 洋溢o5l502fgf3 2018-04-08
王小新 編譯自 FloydHub Blog
量子位 出品 | 公眾號(hào) QbitAI

昨天,,你可能驚喜地看到了Adobe做了個(gè)給人像上色的軟件,然后傷心地發(fā)現(xiàn)只能搞定人臉,,而且還沒(méi)正式推出,,現(xiàn)在能看到的只有一篇論文……

沒(méi)關(guān)系,咱們自己做一個(gè),。

深度學(xué)習(xí)云平臺(tái)FloydHub最近在官方博客上發(fā)了一篇教你搭建神經(jīng)網(wǎng)絡(luò),,來(lái)給黑白照片上色的教程,在Twitter和Reddit論壇上都廣受好評(píng),。

FloydHub是個(gè)YC孵化的創(chuàng)業(yè)公司,,號(hào)稱要做深度學(xué)習(xí)領(lǐng)域的Heroku。它在GPU系統(tǒng)上預(yù)裝了TensorFlow和很多其他的機(jī)器學(xué)習(xí)工具,,用戶可以按時(shí)長(zhǎng)租用,,訓(xùn)練自己的機(jī)器學(xué)習(xí)模型。

這份教程是基于FloydHub平臺(tái)寫的,,這個(gè)平臺(tái)號(hào)稱深度學(xué)習(xí)領(lǐng)域的Heroku,,在GPU系統(tǒng)上預(yù)裝了TensorFlow和很多其他的機(jī)器學(xué)習(xí)工具,,用戶可以按時(shí)長(zhǎng)租用,訓(xùn)練自己的機(jī)器學(xué)習(xí)模型,。免費(fèi)版支持1個(gè)項(xiàng)目,、每月20小時(shí)GPU時(shí)長(zhǎng)、10G存儲(chǔ)空間,,用上色項(xiàng)目練個(gè)手足夠了,。

進(jìn)入正題~

以下內(nèi)容編譯自FloydHub官方博客:

我將分三個(gè)步驟展示如何打造你自己的著色神經(jīng)網(wǎng)絡(luò)。

第一部分介紹核心邏輯,。我們將用40行代碼來(lái)構(gòu)建一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò),,叫做“Alpha”版本著色機(jī)器人。這個(gè)代碼里沒(méi)有太多技巧,,但是這有助于熟悉語(yǔ)法,。

下一步是創(chuàng)建一個(gè)具備泛化能力的神經(jīng)網(wǎng)絡(luò),叫做“Beta”版本,,它能夠?qū)σ郧皼](méi)見(jiàn)過(guò)的圖像進(jìn)行著色,。

最后,將神經(jīng)網(wǎng)絡(luò)與分類器相結(jié)合,,得到最終版本,。Inception Resnet V2是訓(xùn)練120萬(wàn)張圖像后得到的神經(jīng)網(wǎng)絡(luò),我們使用了該模型,。為了使著色效果更加吸引人,,我們使用了來(lái)自素材網(wǎng)站Unsplash的人像集,來(lái)訓(xùn)練這個(gè)神經(jīng)網(wǎng)絡(luò),。

Alpha版本機(jī)器人的Jupyter Notebook代碼,、上述三個(gè)版本實(shí)現(xiàn)代碼的FloydHub和GitHub地址,以及在FloydHub的GPU云上運(yùn)行的所有實(shí)驗(yàn)代碼,,都在文末,。

核心邏輯

在本節(jié)中,我將概述如何渲染圖像,、數(shù)字顏色的基礎(chǔ)知識(shí)以及神經(jīng)網(wǎng)絡(luò)的主要邏輯,。

黑白圖像可以在像素網(wǎng)格中表示。每個(gè)像素有對(duì)應(yīng)于其亮度的值,,取值范圍為0 - 255,,從黑色到白色。

 圖像與數(shù)字的對(duì)應(yīng)

彩色圖像可以分為三層,,分別是紅色層,、綠色層和藍(lán)色層。直觀上,,你可能會(huì)認(rèn)為植物只存在于綠色層,,這可能與你的直覺(jué)相反,。想象一下,將白色背景上的綠葉分成三個(gè)圖層,。

如下圖所示,,葉子在三個(gè)圖層中都存在。這些層不僅可以確定顏色,,還確定了亮度,。

 三個(gè)通道的綠葉

例如,為了得到白色這個(gè)顏色,,你需要將所有顏色均勻分布,。添加等量紅色和藍(lán)色后,綠色會(huì)變得更亮,。因此,,彩色圖像使用三個(gè)通道來(lái)編碼顏色和對(duì)比度:

 RGB調(diào)色

就像黑白圖像一樣,彩色圖像中每個(gè)圖層值的范圍也是0 – 255,,值為0意味著該圖層中沒(méi)有顏色,。如果在所有顏色圖層中該值都為0,則該圖像像素為黑色,。

神經(jīng)網(wǎng)絡(luò)能建立輸入和輸出之間的關(guān)系,。更準(zhǔn)確地說(shuō),著色任務(wù)就是讓網(wǎng)絡(luò)找到連接灰度圖像與彩色圖像的特征,。

因此,,著色神經(jīng)網(wǎng)絡(luò),就是要尋找將灰度值網(wǎng)格連接到三色網(wǎng)格的特征,。

Alpha版本

我們從簡(jiǎn)單版本開始,建立一個(gè)能給女性臉部著色的神經(jīng)網(wǎng)絡(luò),。這樣,,當(dāng)添加新特征時(shí),你可以熟悉已有模型的核心語(yǔ)法,。

只需要40行代碼,,就能實(shí)現(xiàn)下圖所示的轉(zhuǎn)換。中間圖像是用神經(jīng)網(wǎng)絡(luò)完成的,,右邊圖像是原始的彩色照片,。這個(gè)網(wǎng)絡(luò)使用了相同圖像做訓(xùn)練和測(cè)試,在beta版本中還會(huì)再講這一點(diǎn),。

顏色空間

首先,,使用一種能改變顏色通道的算法,從RGB到Lab,。其中,,L表示亮度,,a和b分別表示顏色光譜,綠-紅和藍(lán)-黃,。

如下所示,,Lab編碼的圖像具有一個(gè)灰度層,并將三個(gè)顏色層壓成兩層,,這意味著在最終預(yù)測(cè)中可以使用原始灰度圖像,。此外,我們只需預(yù)測(cè)兩個(gè)通道,。

 Lab編碼圖像

科學(xué)研究表明,,人類眼睛中有94%細(xì)胞確定著亮度,只有6%細(xì)胞是用來(lái)感受顏色的,。如上圖所示,,灰度圖像比彩色層更加清晰。這是我們?cè)谧罱K預(yù)測(cè)中保留灰度圖像的另一個(gè)原因,。

從黑白到彩色

最終預(yù)測(cè)應(yīng)該是這樣的:向網(wǎng)絡(luò)輸入灰度層(L),,然后預(yù)測(cè)Lab中的兩個(gè)顏色層ab。要?jiǎng)?chuàng)建最終輸出的彩色圖像,,我們需要把輸入的灰度(L)圖像和輸出的a,、b層加在一起,創(chuàng)建一個(gè)Lab圖像,。

 圖像轉(zhuǎn)化函數(shù)

我們使用卷積過(guò)濾器將一層變成兩層,,可以把它們看作3D眼鏡中的藍(lán)色和紅色濾鏡。每個(gè)過(guò)濾器確定能從圖片中看到的內(nèi)容,,可以突出或移除某些東西,,來(lái)從圖片中提取信息。這個(gè)網(wǎng)絡(luò)可以從過(guò)濾器中創(chuàng)建新圖像,,也可以組合多個(gè)過(guò)濾器形成新圖像,。

卷積神經(jīng)網(wǎng)絡(luò)能自動(dòng)調(diào)整每個(gè)濾波器,以達(dá)到預(yù)期結(jié)果,。我們將從堆疊數(shù)百個(gè)濾波器開始,,然后將它們縮小成兩層,即a層和b層,。

在詳細(xì)介紹其工作原理之前,,先介紹代碼。

在FloydHub上部署代碼

如果你剛接觸FloydHub,,請(qǐng)看這個(gè)2分鐘安裝教程(https://www./),,以及手把手教學(xué)指南(https://blog./my-first-weekend-of-deep-learning/),然后就可以開始在GPU云上訓(xùn)練深度學(xué)習(xí)模型了,。

Alpha版本

安裝好FloydHub后,,執(zhí)行以下命令:

git clone https://github.com/emilwallner/Coloring-greyscale-images-in-Keras

打開文件夾并啟動(dòng)FloydHub,。

cd Coloring-greyscale-images-in-Keras/floydhub floyd init colornet

FloydHub Web控制臺(tái)將在瀏覽器中打開,系統(tǒng)會(huì)提示你創(chuàng)建一個(gè)名為colornet的FloydHub新項(xiàng)目,。完成后,,返回終端并執(zhí)行相同的初始化命令。

floyd init colornet

接下來(lái)執(zhí)行本項(xiàng)目任務(wù),。

floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard

對(duì)于這個(gè)任務(wù)的一些簡(jiǎn)單說(shuō)明:

1. 我們?cè)贔loydHub的數(shù)據(jù)集目錄(—data emilwallner / datasets / colornet / 2:data)中載入了一個(gè)公開數(shù)據(jù)集,,你在FloydHub上查看并使用此數(shù)據(jù)集和許多其他公開數(shù)據(jù)集;

2. 啟用了Tensorboard (—tensorboard),;

3. 在Jupyter Notebook下運(yùn)行代碼 (—mode jupyter),;

4. 如果能使用GPU,你還可以將GPU (—gpu)添加到命令中,,這樣運(yùn)行速度能提高50倍,。

在FloydHub網(wǎng)站上的選項(xiàng)“Jobs”下,點(diǎn)擊Jupyter Notebook可鏈接到以下文件:floydhub / Alpha version / working_floyd_pink_light_full.ipynb,,打開它并摁下shift enter,。

逐漸增大epoch值,體會(huì)神經(jīng)網(wǎng)絡(luò)是如何學(xué)習(xí)的,。

model.fit(x=X, y=Y, batch_size=1, epochs=1)

開始時(shí)把epoch設(shè)置為1,,逐漸增加到10、100,、5500,、1000和3000。epoch值表示神經(jīng)網(wǎng)絡(luò)從圖像中學(xué)習(xí)的次數(shù),。在訓(xùn)練神經(jīng)網(wǎng)絡(luò)的過(guò)程中,,你可以在主文件夾中找到這個(gè)圖像img_result.png。

# Get images image = img_to_array(load_img('woman.png')) image = np.array(image, dtype=float) # Import map images into the lab colorspace X = rgb2lab(1.0/255*image)[:,:,0] Y = rgb2lab(1.0/255*image)[:,:,1:] Y = Y / 128 X = X.reshape(1, 400, 400, 1) Y = Y.reshape(1, 400, 400, 2) model = Sequential() model.add(InputLayer(input_shape=(None, None, 1))) # Building the neural network model = 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 model model.compile(optimizer='rmsprop',loss='mse') #Train the neural network model.fit(x=X, y=Y, batch_size=1, epochs=3000) print(model.evaluate(X, Y, batch_size=1)) # Output colorizations output = model.predict(X) output = output * 128 canvas = np.zeros((400, 400, 3)) canvas[:,:,0] = X[0][:,:,0] canvas[:,:,1:] = output[0] imsave('img_result.png', lab2rgb(cur)) imsave('img_gray_scale.png', rgb2gray(lab2rgb(cur)))

用FloydHub命令來(lái)運(yùn)行網(wǎng)絡(luò):

floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard

技術(shù)說(shuō)明

總的來(lái)說(shuō),,輸入是一個(gè)黑白圖像網(wǎng)格,,輸出兩個(gè)具有顏色值的網(wǎng)格。在輸入和輸出之間,,通過(guò)一個(gè)卷積神經(jīng)網(wǎng)絡(luò),構(gòu)建過(guò)濾器連接兩者,。

訓(xùn)練網(wǎng)絡(luò)時(shí)使用的是彩色圖像,,并將RGB顏色轉(zhuǎn)換成Lab顏色空間。網(wǎng)絡(luò)輸入為黑白圖層,,輸出兩個(gè)著色層,。

在上圖左側(cè),輸入為黑白網(wǎng)格,、過(guò)濾器和神經(jīng)網(wǎng)絡(luò)的預(yù)測(cè)結(jié)果,。

在同一變化間距內(nèi),,比較預(yù)測(cè)值和實(shí)際值的差異。其中,,該間距為[-1, 1],。為了映射這些預(yù)測(cè)值,我們使用Tanh激活函數(shù),,因?yàn)門anh函數(shù)的輸入可為任意值,,輸出為-1到1。

實(shí)際上,,顏色值的分布區(qū)間為[-128, 128],,這也是Lab顏色空間的默認(rèn)間距。除以128后這些值也落到區(qū)間[-1, 1]中,,這樣就能用來(lái)比較預(yù)測(cè)結(jié)果的誤差,。

計(jì)算得到最終誤差后,網(wǎng)絡(luò)會(huì)更新過(guò)濾器以減小全局誤差,。網(wǎng)絡(luò)會(huì)留在這個(gè)循環(huán),,直到誤差達(dá)到足夠小。

下面解釋下代碼的一些語(yǔ)法,。

X = rgb2lab(1.0/255*image)[:,:,0] Y = rgb2lab(1.0/255*image)[:,:,1:]

1.0 / 255表示彩色圖像使用的RGB顏色空間為24位,,也就是說(shuō)每個(gè)顏色通道值為整數(shù),且從0到255變化,。這是標(biāo)準(zhǔn)顏色范圍,,一共有1670萬(wàn)種顏色組合。由于人類只能感知到2 ~ 10萬(wàn)種顏色,,因此使用更大的顏色空間沒(méi)有太大意義,。

Y = Y / 128

與RGB相比,Lab顏色空間的范圍與其不同,。Lab中色譜ab的取值范圍是[-128, 128],。將輸出層的所有值都除以128,它的范圍變成[-1, 1],。神經(jīng)網(wǎng)絡(luò)的輸出值范圍也為[-1, 1],,兩者可進(jìn)行匹配。

在用rgb2lab()函數(shù)轉(zhuǎn)換顏色空間后,,我們使用[:,,…,0]來(lái)選擇灰度層,,這是神經(jīng)網(wǎng)絡(luò)的輸入,。同時(shí)[:,…,1:]表示選擇兩個(gè)顏色層,,綠-紅和藍(lán)-黃,。

訓(xùn)練好神經(jīng)網(wǎng)絡(luò)后,轉(zhuǎn)換回Lab圖像,,作最終預(yù)測(cè),。

output = model.predict(X) output = output * 128

其中,輸入為灰度圖像,,經(jīng)過(guò)訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)后,,其輸出位于區(qū)間[-1, 1],再將其乘以128,,得到Lab色譜中的合適顏色,。

canvas = np.zeros((400, 400, 3)) canvas[:,:,0] = X[0][:,:,0] canvas[:,:,1:] = output[0]

最后,用0填充三個(gè)圖層得到一個(gè)全黑RGB畫布,,然后從測(cè)試圖像中復(fù)制灰度圖層,,再把兩個(gè)顏色層添加到RGB畫布中,最后把這個(gè)像素?cái)?shù)組轉(zhuǎn)換回圖像,。

打造Alpha版本的一些心得

1. 閱讀研究論文是很痛苦的,。但只要你能總結(jié)出每篇論文的核心要點(diǎn),就能輕松地閱讀論文,,也讓你更關(guān)注于文中的前后關(guān)聯(lián),。

2. 關(guān)鍵是要從簡(jiǎn)化版開始。網(wǎng)上大多數(shù)實(shí)現(xiàn)的代碼行數(shù)可達(dá)2000行到10000行,,這讓我很難去理解問(wèn)題的核心邏輯,。只要有了一個(gè)準(zhǔn)系統(tǒng)版本,之后就能更容易去閱讀實(shí)現(xiàn)代碼和研究論文,。

3.探索開源項(xiàng)目,。為了大體了解如何編程,我在Github上瀏覽了50-100個(gè)關(guān)于著色的項(xiàng)目,。

4.事情并不總是像預(yù)期的那樣工作,。開始時(shí),我的網(wǎng)絡(luò)只能創(chuàng)建紅色和黃色,。最初,,末層激活時(shí)用的是Relu激活函數(shù)。因?yàn)樗荒軐?shù)字映射為正數(shù),,無(wú)法得到負(fù)值和藍(lán)綠色譜,。后來(lái),我添加了一個(gè)Tanh激活函數(shù)來(lái)映射Y值,,解決了這個(gè)問(wèn)題。

5.理解比速度更重要。我看到,,很多實(shí)現(xiàn)代碼的運(yùn)行速度都很快,,但很難看懂。我選擇優(yōu)化創(chuàng)新速度而不是代碼速度,。

Beta版本

要了解Alpha版本的缺點(diǎn),,用該網(wǎng)絡(luò)給未經(jīng)訓(xùn)練的圖像著色。嘗試后你就會(huì)發(fā)現(xiàn)它的效果不好,,因?yàn)榫W(wǎng)絡(luò)只記住了已有的信息,,還沒(méi)有學(xué)會(huì)如何給未見(jiàn)過(guò)的圖像著色。而這正是我們要在Beta版本中努力的方向,,即提高網(wǎng)絡(luò)的泛化能力,。

以下是Beta版本神經(jīng)網(wǎng)絡(luò)在驗(yàn)證圖像上的著色結(jié)果。

我在FloydHub上創(chuàng)建了一個(gè)公開的高質(zhì)量圖像數(shù)據(jù)集,,而不是使用現(xiàn)有的Imagenet,。Unsplash收集了大量專業(yè)攝影師的創(chuàng)意共享圖片,本數(shù)據(jù)集圖像來(lái)自于此,,一共包括了9500張訓(xùn)練圖像和500張驗(yàn)證圖像,。

特征提取器

我們所構(gòu)建的神經(jīng)網(wǎng)絡(luò)能找到灰度圖與其彩色版本相關(guān)聯(lián)的有效特征。

試想一下,,你必須給黑白圖像著色,,但是限制你每次只能看到九個(gè)像素。你只能從左上角到右下角來(lái)掃描每張圖像,,并嘗試預(yù)測(cè)每個(gè)像素可能的顏色值,。

例如,這九個(gè)像素就是上面那個(gè)女性的鼻孔邊緣,。想象得到,,這很難得到一個(gè)良好的著色效果,所以可將它分解成多個(gè)步驟,。

首先,,你要尋找簡(jiǎn)單圖案,如對(duì)角線和黑色像素等,。你也可以在每個(gè)方塊中尋找相同的確切圖案,,并刪除不匹配的像素。具體做法是使用最開始的64個(gè)過(guò)濾器來(lái)生成64張新圖像,。

當(dāng)再次掃描圖像時(shí),,你會(huì)看到已經(jīng)檢測(cè)到的相同小圖案。要獲得對(duì)圖像的更深入理解,,你可以將圖像分辨率減半,。

你仍然只用了3×3過(guò)濾器來(lái)掃描每張圖像,。但是,通過(guò)將9個(gè)新像素與較低層次濾波器相結(jié)合,,你可以檢測(cè)更復(fù)雜的圖案,。幾個(gè)像素組合起來(lái),可能會(huì)形成一個(gè)半圓,、一個(gè)小點(diǎn)或是一條線,。此外,你可以反復(fù)從圖像中提取相同圖案,,這樣就能生成128個(gè)過(guò)濾后的新圖像,。

經(jīng)過(guò)幾次操作后,過(guò)濾后的新圖像可能會(huì)像這樣:

如上所述,,先提取低層特征,,如邊緣等。越靠近輸出的圖層先組合成圖案,,再組合成局部細(xì)節(jié),,最終轉(zhuǎn)化為面部。如果你覺(jué)得難以理解,,可觀看這個(gè)視頻教程(https://www./watch?v=AgkfIQ4IGaM),。

這個(gè)過(guò)程與用于處理圖像的神經(jīng)網(wǎng)絡(luò)相似,被稱為卷積神經(jīng)網(wǎng)絡(luò),。卷積運(yùn)算與單詞組合相似,,通過(guò)組合若干個(gè)過(guò)濾后的圖像來(lái)理解圖像中的前后關(guān)系。

從特征提取到著色

神經(jīng)網(wǎng)絡(luò)以誤差傳遞的方式實(shí)現(xiàn),。首先,,它對(duì)每個(gè)像素進(jìn)行隨機(jī)預(yù)測(cè);然后基于每個(gè)像素的誤差,,通過(guò)反向傳播,,來(lái)改進(jìn)特征提取效果。

開始時(shí),,它會(huì)先調(diào)整具有最大誤差的位置,。因此,最初只考慮兩個(gè)問(wèn)題,,即是否要著色和是否定位不同物體,;然后給所有物體涂上棕色,因?yàn)檫@是與其他顏色最相似的一種顏色,,能產(chǎn)生最小的誤差,。

由于大多數(shù)訓(xùn)練數(shù)據(jù)非常相似,網(wǎng)絡(luò)只能通過(guò)調(diào)整棕色的深淺程度來(lái)區(qū)分不同物體,,但是不能產(chǎn)生更細(xì)致的顏色,,這也是我們將在最終版本中探索的內(nèi)容,。

以下是beta版本的代碼,及技術(shù)說(shuō)明,。

# Get images X = [] for filename in os.listdir('../Train/'):    X.append(img_to_array(load_img('../Train/' filename))) X = np.array(X, dtype=float) # Set up training and test data split = int(0.95*len(X)) Xtrain = X[:split] Xtrain = 1.0/255*Xtrain #Design the neural network model = Sequential() model.add(InputLayer(input_shape=(256, 256, 1))) model.add(Conv2D(64, (3, 3), activation='relu', padding='same')) model.add(Conv2D(64, (3, 3), activation='relu', padding='same', strides=2)) model.add(Conv2D(128, (3, 3), activation='relu', padding='same')) model.add(Conv2D(128, (3, 3), activation='relu', padding='same', strides=2)) model.add(Conv2D(256, (3, 3), activation='relu', padding='same')) model.add(Conv2D(256, (3, 3), activation='relu', padding='same', strides=2)) model.add(Conv2D(512, (3, 3), activation='relu', padding='same')) model.add(Conv2D(256, (3, 3), activation='relu', padding='same')) model.add(Conv2D(128, (3, 3), activation='relu', padding='same')) model.add(UpSampling2D((2, 2))) model.add(Conv2D(64, (3, 3), activation='relu', padding='same')) model.add(UpSampling2D((2, 2))) model.add(Conv2D(32, (3, 3), activation='relu', padding='same')) model.add(Conv2D(2, (3, 3), activation='tanh', padding='same')) model.add(UpSampling2D((2, 2))) # Finish model model.compile(optimizer='rmsprop', loss='mse') # Image transformer datagen = ImageDataGenerator(        shear_range=0.2,        zoom_range=0.2,        rotation_range=20,        horizontal_flip=True) # Generate training data batch_size = 50 def image_a_b_gen(batch_size):    for batch in datagen.flow(Xtrain, batch_size=batch_size):        lab_batch = rgb2lab(batch)        X_batch = lab_batch[:,:,:,0]        Y_batch = lab_batch[:,:,:,1:] / 128        yield (X_batch.reshape(X_batch.shape (1,)), Y_batch) # Train model TensorBoard(log_dir='/output') model.fit_generator(image_a_b_gen(batch_size), steps_per_epoch=10000, epochs=1) # Test images Xtest = rgb2lab(1.0/255*X[split:])[:,:,:,0] Xtest = Xtest.reshape(Xtest.shape (1,)) Ytest = rgb2lab(1.0/255*X[split:])[:,:,:,1:] Ytest = Ytest / 128 print model.evaluate(Xtest, Ytest, batch_size=batch_size) # Load black and white images color_me = [] for filename in os.listdir('../Test/'):        color_me.append(img_to_array(load_img('../Test/' filename))) color_me = np.array(color_me, dtype=float) color_me = rgb2lab(1.0/255*color_me)[:,:,:,0] color_me = color_me.reshape(color_me.shape (1,)) # Test model output = model.predict(color_me) output = output * 128 # Output colorizations for i in range(len(output)):        cur = np.zeros((256, 256, 3))        cur[:,:,0] = color_me[i][:,:,0]        cur[:,:,1:] = output[i]        imsave('result/img_' str(i) '.png', lab2rgb(cur))

用FloydHub命令來(lái)運(yùn)行Beta版本神經(jīng)網(wǎng)絡(luò):

floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard

技術(shù)說(shuō)明

與其他視覺(jué)網(wǎng)絡(luò)不同,,它的主要區(qū)別在于像素位置的重要性。在著色網(wǎng)絡(luò)中,,圖像的分辨率或比例在整個(gè)網(wǎng)絡(luò)中保持不變。而在其他網(wǎng)絡(luò)中,,越靠近最后一層,,圖像變得越扭曲。

分類網(wǎng)絡(luò)中的最大池化層增加了信息密度,,但也可能導(dǎo)致圖像失真,。它只對(duì)信息進(jìn)行估值,而未考慮到圖像布局,。在著色網(wǎng)絡(luò)中,,我們將步幅改為2,每次運(yùn)算使寬度和高度減半,。這樣,,不但增加了信息密度,也不會(huì)使圖像扭曲,。

兩者差異在于上采樣層和圖像比例保持方面,。而分類網(wǎng)絡(luò)只關(guān)心最終的分類正確率,因此隨著網(wǎng)絡(luò)深入,,它會(huì)不斷減小圖像的分辨率和質(zhì)量,。

但是,著色網(wǎng)絡(luò)的圖像比例保持不變,。這是通過(guò)添加空白填充來(lái)實(shí)現(xiàn)的,,否則每個(gè)卷積層將削減圖像,實(shí)現(xiàn)代碼為:padding =’same’,。

要使圖像的分辨率加倍,,著色網(wǎng)絡(luò)使用了上采樣層,更多信息見(jiàn):https:///layers/convolutional/#upsampling2d,。

for filename in os.listdir('/Color_300/Train/'):    X.append(img_to_array(load_img('/Color_300/Test' filename)))

這個(gè)for循環(huán)首先計(jì)算了目錄中的所有文件名,,然后遍歷圖像目錄,并將圖像轉(zhuǎn)換為像素?cái)?shù)組,,最后將其組合成一個(gè)大型矢量,。

datagen = ImageDataGenerator(        shear_range=0.2,        zoom_range=0.2,        rotation_range=20,        horizontal_flip=True)

在ImageDataGenerator中,我們還修改了圖像生成器的參數(shù),。這樣,,圖像永遠(yuǎn)不會(huì)相同,,以改善學(xué)習(xí)效果。參數(shù)shear_range是指圖像向左或向右的傾斜程度,,其他參數(shù)不需要加以說(shuō)明,。

batch_size = 50 def image_a_b_gen(batch_size):    for batch in datagen.flow(Xtrain, batch_size=batch_size):        lab_batch = rgb2lab(batch)        X_batch = lab_batch[:,:,:,0]        Y_batch = lab_batch[:,:,:,1:] / 128        yield (X_batch.reshape(X_batch.shape (1,)), Y_batch)

我們使用了文件夾Xtrain中的圖像,根據(jù)之前設(shè)置來(lái)生成圖像,。然后我們提取X_batch中的黑白層和兩個(gè)顏色層的兩種顏色,。

model.fit_generator(image_a_b_gen(batch_size), steps_per_epoch=1, epochs=1000)

擁有越高性能的GPU,則可以設(shè)置越大的batch_size值,。根據(jù)現(xiàn)有硬件,,我們?cè)O(shè)置了每批次輸入50-100張圖像。參數(shù)steps_per_epoch是通過(guò)把訓(xùn)練圖像的數(shù)量除以批次大小得出的,。例如,,有100張圖像且批次大小為50,則steps_per_epoch值為2,。參數(shù)epoch決定網(wǎng)絡(luò)中所有圖像的訓(xùn)練次數(shù),。在Tesla K80 GPU上,大約需要11小時(shí)才能完成對(duì)1萬(wàn)張圖像的21次訓(xùn)練,。

訓(xùn)練心得

1.先進(jìn)行多次小批次實(shí)驗(yàn),,再嘗試大批次實(shí)驗(yàn)。即使經(jīng)過(guò)20-30次實(shí)驗(yàn),,我仍然發(fā)現(xiàn)很多錯(cuò)誤,。程序能運(yùn)行并不意味著它能工作。神經(jīng)網(wǎng)絡(luò)中的問(wèn)題通常比傳統(tǒng)編程遇到的Bug更為麻煩,。

2.多樣化的數(shù)據(jù)集會(huì)使著色效果呈現(xiàn)棕色,。如果數(shù)據(jù)集中圖像比較相似,不需要設(shè)計(jì)很復(fù)雜的架構(gòu),,就可以得到一個(gè)良好效果,,但是其泛化能力十分糟糕。

3.重視圖像形狀的統(tǒng)一性,。每張圖像的分辨率必須是準(zhǔn)確的,,且在整個(gè)網(wǎng)絡(luò)中保持成比例。開始時(shí),,所使用的圖像分辨率為300,,將它減半三次后分別得到150、75和35.5,。因此,,就丟失了半個(gè)像素,這導(dǎo)致了很多問(wèn)題,,后來(lái)才意識(shí)到應(yīng)該使用4,、8,、16、32,、64,、256等這種能被2整除的數(shù)。

4.創(chuàng)建數(shù)據(jù)集,。請(qǐng)禁用.DS_Store文件,,不然會(huì)產(chǎn)生很多麻煩;大膽創(chuàng)新,,最后我用Chrome控制臺(tái)腳本和擴(kuò)展程序來(lái)下載文件,;備份原始文件并構(gòu)建清理腳本。

最終版本

最終版本的著色神經(jīng)網(wǎng)絡(luò)有四個(gè)組成部分,。我們將之前的網(wǎng)絡(luò)拆分成編碼器和解碼器,在這兩者之間還添加了一個(gè)融合層,。關(guān)于分類網(wǎng)絡(luò)的基本教程,,可參考:https://cs231n./classification/。

Inception resnet v2是目前最強(qiáng)大的分類器之一,,使用了120萬(wàn)張圖像來(lái)訓(xùn)練該網(wǎng)絡(luò),。我們提取了它的分類層,并將其與編碼器的輸出進(jìn)行合并,。因此,,輸入數(shù)據(jù)傳給編碼器的同時(shí),也并行傳輸?shù)絩esnet v2網(wǎng)絡(luò)的分類層中,。更多信息,,請(qǐng)參考原論文:https://github.com/baldassarreFe/deep-koalarization。

 信息并行傳輸示意圖

這個(gè)網(wǎng)絡(luò)通過(guò)將分類器的學(xué)習(xí)效果遷移到著色網(wǎng)絡(luò)上,,可更好理解圖片中的內(nèi)容,。因此,這樣使得網(wǎng)絡(luò)能夠把目標(biāo)表征與著色方案相匹配,。

以下是在一些驗(yàn)證圖像上的著色效果,,僅使用20張圖像來(lái)訓(xùn)練網(wǎng)絡(luò)。

大多數(shù)圖像的著色效果不好,,但是由于驗(yàn)證集中有2500張圖像,,我設(shè)法找到了一些良好的著色圖像。在更多圖像上進(jìn)行訓(xùn)練可以獲得更為穩(wěn)定的結(jié)果,,但是大部分都呈現(xiàn)棕色色調(diào),。這兩個(gè)鏈接貼出了運(yùn)行試驗(yàn)的完整列表,包括驗(yàn)證圖像(https://www./emilwallner/projects/color) (https://www./emilwallner/projects/color_full),。

本文的神經(jīng)網(wǎng)絡(luò)設(shè)計(jì)參考了這篇論文(https://github.com/baldassarreFe/deep-koalarization/blob/master/report.pdf),,以及我在Keras中的一些理解,。

注意:在下面代碼中,我把Keras的序列模型變換成相應(yīng)的函數(shù)調(diào)用,。

# Get images X = [] for filename in os.listdir('/data/images/Train/'):    X.append(img_to_array(load_img('/data/images/Train/' filename))) X = np.array(X, dtype=float) Xtrain = 1.0/255*X #Load weights inception = InceptionResNetV2(weights=None, include_top=True) inception.load_weights('/data/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels.h5') inception.graph = tf.get_default_graph() embed_input = Input(shape=(1000,)) #Encoder encoder_input = Input(shape=(256, 256, 1,)) encoder_output = Conv2D(64, (3,3), activation='relu', padding='same', strides=2)(encoder_input) encoder_output = Conv2D(128, (3,3), activation='relu', padding='same')(encoder_output) encoder_output = Conv2D(128, (3,3), activation='relu', padding='same', strides=2)(encoder_output) encoder_output = Conv2D(256, (3,3), activation='relu', padding='same')(encoder_output) encoder_output = Conv2D(256, (3,3), activation='relu', padding='same', strides=2)(encoder_output) encoder_output = Conv2D(512, (3,3), activation='relu', padding='same')(encoder_output) encoder_output = Conv2D(512, (3,3), activation='relu', padding='same')(encoder_output) encoder_output = Conv2D(256, (3,3), activation='relu', padding='same')(encoder_output) #Fusion fusion_output = RepeatVector(32 * 32)(embed_input) fusion_output = Reshape(([32, 32, 1000]))(fusion_output) fusion_output = concatenate([encoder_output, fusion_output], axis=3) fusion_output = Conv2D(256, (1, 1), activation='relu', padding='same')(fusion_output) #Decoder decoder_output = Conv2D(128, (3,3), activation='relu', padding='same')(fusion_output) decoder_output = UpSampling2D((2, 2))(decoder_output) decoder_output = Conv2D(64, (3,3), activation='relu', padding='same')(decoder_output) decoder_output = UpSampling2D((2, 2))(decoder_output) decoder_output = Conv2D(32, (3,3), activation='relu', padding='same')(decoder_output) decoder_output = Conv2D(16, (3,3), activation='relu', padding='same')(decoder_output) decoder_output = Conv2D(2, (3, 3), activation='tanh', padding='same')(decoder_output) decoder_output = UpSampling2D((2, 2))(decoder_output) model = Model(inputs=[encoder_input, embed_input], outputs=decoder_output) #Create embedding def create_inception_embedding(grayscaled_rgb):    grayscaled_rgb_resized = []    for i in grayscaled_rgb:        i = resize(i, (299, 299, 3), mode='constant')        grayscaled_rgb_resized.append(i)    grayscaled_rgb_resized = np.array(grayscaled_rgb_resized)    grayscaled_rgb_resized = preprocess_input(grayscaled_rgb_resized)    with inception.graph.as_default():        embed = inception.predict(grayscaled_rgb_resized)    return embed # Image transformer datagen = ImageDataGenerator(        shear_range=0.4,        zoom_range=0.4,        rotation_range=40,        horizontal_flip=True) #Generate training data batch_size = 20 def image_a_b_gen(batch_size):    for batch in datagen.flow(Xtrain, batch_size=batch_size):        grayscaled_rgb = gray2rgb(rgb2gray(batch))        embed = create_inception_embedding(grayscaled_rgb)        lab_batch = rgb2lab(batch)        X_batch = lab_batch[:,:,:,0]        X_batch = X_batch.reshape(X_batch.shape (1,))        Y_batch = lab_batch[:,:,:,1:] / 128        yield ([X_batch, create_inception_embedding(grayscaled_rgb)], Y_batch) #Train model       tensorboard = TensorBoard(log_dir='/output') model.compile(optimizer='adam', loss='mse') model.fit_generator(image_a_b_gen(batch_size), callbacks=[tensorboard], epochs=1000, steps_per_epoch=20) #Make a prediction on the unseen images color_me = [] for filename in os.listdir('../Test/'):    color_me.append(img_to_array(load_img('../Test/' filename))) color_me = np.array(color_me, dtype=float) color_me = 1.0/255*color_me color_me = gray2rgb(rgb2gray(color_me)) color_me_embed = create_inception_embedding(color_me) color_me = rgb2lab(color_me)[:,:,:,0] color_me = color_me.reshape(color_me.shape (1,)) # Test model output = model.predict([color_me, color_me_embed]) output = output * 128 # Output colorizations for i in range(len(output)):    cur = np.zeros((256, 256, 3))    cur[:,:,0] = color_me[i][:,:,0]    cur[:,:,1:] = output[i]    imsave('result/img_' str(i) '.png', lab2rgb(cur))

用FloydHub命令來(lái)運(yùn)行最終版本神經(jīng)網(wǎng)絡(luò):

floyd run --data emilwallner/datasets/colornet/2:data --mode jupyter --tensorboard

技術(shù)說(shuō)明

當(dāng)你要實(shí)現(xiàn)模型連接或模型融合時(shí),,Keras的函數(shù)調(diào)用功能是最佳選擇。

 模型融合層

首先,,要下載inception resnet v2網(wǎng)絡(luò)并加載權(quán)重,。由于要并行使用兩個(gè)模型,因此必須指定當(dāng)前要使用哪個(gè)模型,。這個(gè)可通過(guò)Keras的后端Tensorflow來(lái)完成,。

inception = InceptionResNetV2(weights=None, include_top=True) inception.load_weights('/data/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels.h5') inception.graph = tf.get_default_graph()

批處理方法中使用了調(diào)整后的圖像,把它們變成黑白圖像,,并在inception resnet模型上運(yùn)行,。

grayscaled_rgb = gray2rgb(rgb2gray(batch)) embed = create_inception_embedding(grayscaled_rgb)

首先,要調(diào)整圖像分辨率以適應(yīng)inception模型,;然后根據(jù)模型,,使用預(yù)處理程序來(lái)規(guī)范化像素和顏色值;最后,,在inception網(wǎng)絡(luò)上運(yùn)行并提取模型最后一層的權(quán)重,。

def create_inception_embedding(grayscaled_rgb):    grayscaled_rgb_resized = []    for i in grayscaled_rgb:        i = resize(i, (299, 299, 3), mode='constant')        grayscaled_rgb_resized.append(i)    grayscaled_rgb_resized = np.array(grayscaled_rgb_resized)    grayscaled_rgb_resized = preprocess_input(grayscaled_rgb_resized)    with inception.graph.as_default():        embed = inception.predict(grayscaled_rgb_resized)    return embed

再講下生成器。對(duì)于每個(gè)批次,,我們按照下列格式生成20張圖像,,在Tesla K80 GPU上大約要運(yùn)行一個(gè)小時(shí)?;谠撃P?,每批次最多可輸入50張圖像,且不產(chǎn)生內(nèi)存溢出,。

yield ([X_batch, create_inception_embedding(grayscaled_rgb)], Y_batch) 代碼23

這與本項(xiàng)目中著色模型的格式相匹配,。

model = Model(inputs=[encoder_input, embed_input], outputs=decoder_output)

encoder_input會(huì)輸入到編碼器模型中;接著,,編碼器模型的輸出會(huì)與融合層中的embed_input相融合,;然后,這個(gè)融合輸出會(huì)作為解碼器模型的輸入,;最終,,解碼器模型會(huì)輸出預(yù)測(cè)結(jié)果decode_output。

fusion_output = RepeatVector(32 * 32)(embed_input) fusion_output = Reshape(([32, 32, 1000]))(fusion_output) fusion_output = concatenate([fusion_output, encoder_output], axis=3) fusion_output = Conv2D(256, (1, 1), activation='relu')(fusion_output)

在融合層中,,首先將1000類輸出層乘以1024(即32×32),,這樣就從inception模型的最后一層得到了1024行數(shù)據(jù);接著,把2D重構(gòu)成3D得到一個(gè)具有1000個(gè)類別對(duì)象的32x32網(wǎng)格,;然后,,將它與編碼器模型的輸出相連;最后,,應(yīng)用一個(gè)帶有254個(gè)1X1內(nèi)核的卷積網(wǎng)絡(luò),,得到了融合層的最終輸出。

一些思考

1.不要逃避難懂的術(shù)語(yǔ),。我花了三天時(shí)間去搜索在Keras該如何實(shí)現(xiàn)“融合層”,。因?yàn)檫@聽起來(lái)很復(fù)雜,我不想面對(duì)這個(gè)問(wèn)題,,而是試圖找到現(xiàn)成代碼,。

2.多在網(wǎng)上請(qǐng)教他人。在Keras論壇中,,我提出的問(wèn)題沒(méi)人回答,,同時(shí)Stack Overflow刪除了我的提問(wèn)。但是,,通過(guò)分解成小問(wèn)題去請(qǐng)教他人,,這迫使我進(jìn)一步理解問(wèn)題,并更快解決問(wèn)題,。

3.多發(fā)郵件請(qǐng)教。雖然論壇可能沒(méi)人回應(yīng),,人們關(guān)心你能否直接與他們聯(lián)系,。在Skype上與你不認(rèn)識(shí)的研究人員一起探討問(wèn)題,這聽起來(lái)很有趣,。

4.在解決“融合層”問(wèn)題之前,,我決定構(gòu)建出所有組件。以下是分解融合層的幾個(gè)實(shí)驗(yàn)(https://www./emilwallner/projects/color/24/code/Experiments/transfer-learning-examples),。

5.我以為某些代碼能夠起作用,,但是在猶豫是否要運(yùn)行。雖然我知道核心邏輯是行得通的,,但我不認(rèn)為它會(huì)奏效,。經(jīng)過(guò)一陣糾結(jié),我還是選擇運(yùn)行,。運(yùn)行完模型的第一行代碼后,,就開始報(bào)錯(cuò);四天后,,一共產(chǎn)生幾百個(gè)報(bào)錯(cuò),,我也做了數(shù)千個(gè)Google搜索,模型依舊停留在“Epoch 1/22”。

下一步計(jì)劃

圖像著色是一個(gè)極其有趣的問(wèn)題,。這既是一個(gè)科學(xué)問(wèn)題,,也是一個(gè)藝術(shù)問(wèn)題。我寫下這篇文章,,希望你能從中有所啟發(fā),,以加快在圖像著色方面的研究。以下是一些建議:

1.微調(diào)另一個(gè)預(yù)訓(xùn)練好的模型,;

2.使用不同的數(shù)據(jù)集,;

3.添加更多圖片來(lái)提高網(wǎng)絡(luò)的正確率;

4.在RGB顏色空間中構(gòu)建一個(gè)放大器,。構(gòu)建一個(gè)與著色網(wǎng)絡(luò)類似的模型,,將深色調(diào)的著色圖像作為輸入,它能微調(diào)顏色以輸出合適的著色圖像,;

5.進(jìn)行加權(quán)分類,;

6.應(yīng)用一個(gè)分類神經(jīng)網(wǎng)絡(luò)作為損失函數(shù)。網(wǎng)絡(luò)中錯(cuò)誤分類的圖片有一個(gè)相應(yīng)誤差,,探究每個(gè)像素對(duì)該誤差的貢獻(xiàn)度,。

7.應(yīng)用到視頻中。不要太擔(dān)心著色效果,,而是要關(guān)注如何使圖像切換保持協(xié)調(diào),。你也可以通過(guò)平鋪多張小圖像來(lái)處理大型圖像。

當(dāng)然,,你也可以嘗試用我貼在FloydHub上的三種著色神經(jīng)網(wǎng)絡(luò),,來(lái)給你的黑白圖像著色。

1.對(duì)于Alpha版本,,只需將你的圖片分辨率調(diào)成400x400像素,,把名稱改為woman.jpg,并替換原有文件,。

2.對(duì)于Beta版本和最終版本,,在你運(yùn)行FloydHub命令之前,要將你的圖片放入Test文件夾,。當(dāng)Notebook運(yùn)行時(shí),,你也可以通過(guò)命令行直接上傳到Test文件夾。要注意,,這些圖像的分辨率必須是256x256像素,。此外,你也可以上傳彩色測(cè)試圖像集,,因?yàn)檫@個(gè)網(wǎng)絡(luò)會(huì)自動(dòng)把它們轉(zhuǎn)換為黑白圖像,。

相關(guān)鏈接

1.Alpha版本機(jī)器人的Jupyter Notebook代碼:

https://www./emilwallner/projects/color/43/code/Alpha-version/alpha_version.ipynb

2.三個(gè)版本實(shí)現(xiàn)代碼 - Floydhub傳送門:

https://www./emilwallner/projects/color/43/code

3.三個(gè)版本實(shí)現(xiàn)代碼 - Github傳送門:

https://github.com/emilwallner/Coloring-greyscale-images-in-Keras

4.所有實(shí)驗(yàn)代碼:

https://www./emilwallner/projects/color/jobs

5.作者Twitter:emilwallner https://twitter.com/EmilWallner

6.教程原文:https://blog./colorizing-b&w-photos-with-neural-networks/

加入社群

量子位AI社群10群開始招募啦,歡迎對(duì)AI感興趣的同學(xué),加小助手微信qbitbot3入群,;


此外,,量子位專業(yè)細(xì)分群(自動(dòng)駕駛、CV,、NLP,、機(jī)器學(xué)習(xí)等)正在招募,面向正在從事相關(guān)領(lǐng)域的工程師及研究人員,。


進(jìn)群請(qǐng)加小助手微信號(hào)qbitbot3,,并務(wù)必備注相應(yīng)群的關(guān)鍵詞~通過(guò)審核后我們將邀請(qǐng)進(jìn)群。(專業(yè)群審核較嚴(yán),,敬請(qǐng)諒解)

誠(chéng)摯招聘

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多