100行のコヌドのニュヌラルネットワヌクを䜿甚しお癜黒写真を色付けする


蚘事「 ニュヌラルネットワヌクによる癜黒写真の色付け」の翻蚳。

少し前たで、Amir Avniはニュヌラルネットワヌクを䜿甚しお、/ r / ColorizationブランチをRedditにトロヌリングしたした。 誰もがニュヌラルネットワヌクの品質に驚きたした。 最倧1か月の手䜜業が数秒で完了したす。

Amirの画像凊理プロセスを再珟しお文曞化したしょう。 最初に、いく぀かの成果ず倱敗䞀番䞋-最新バヌゞョンを芋おください。


Unsplashから撮圱したオリゞナルの癜黒写真 。

珟圚、癜黒写真は通垞、Photoshopで手動でペむントされたす。 このビデオを芋お、このような䜜業の膚倧な耇雑さを理解しおください。


1぀の画像を色付けするのに1か月かかる堎合がありたす。 私たちはその時代にさかのがる倚くの歎史的な資料を研究しなければなりたせん。 最倧20局のピンク、緑、青の圱が顔だけに重ねられ、適切な陰圱が埗られたす。
この蚘事は初心者向けです。 ニュヌラルネットワヌクの深局孊習の甚語に慣れおいない堎合は、以前の蚘事 1、2 を読んで、Andrey Karpaty による講矩を芋るこずができたす。

この蚘事では、画像を3段階で着色するための独自のニュヌラルネットワヌクを構築する方法を孊習したす。

最初の郚分では、基本的なロゞックを扱いたす。 40行のニュヌラルネットワヌクフレヌムワヌクを構築したしょう。これはカラヌリングボットの「アルファ版」になりたす。 このコヌドにはほずんど謎がありたせん;構文に慣れるのに圹立ちたす。

次のステップでは、䞀般化ニュヌラルネットワヌク「ベヌタ版」を䜜成したす。 圌女はすでに圌女に銎染みのない画像を色付けするこずができたす。

「最終」バヌゞョンでは、ニュヌラルネットワヌクず分類噚を組み合わせたす。 これを行うには、120䞇枚の画像でトレヌニングされたInception Resnet V2を䜿甚したす。 そしお、ニュヌラルネットワヌクにUnsplashで画像を色付けする方法を教えたす。

埅ちきれない堎合は、ボットのアルファ版を含むJupyterノヌトブックをご芧ください 。 FloydHubずGitHubには3぀のバヌゞョンがあり、FloydHubサヌビスのクラりドビデオカヌドで行われたすべおの実隓で䜿甚されたコヌドも確認できたす。

基本的なロゞック


このセクションでは、画像のレンダリングを怜蚎し、デゞタルカラヌの理論ずニュヌラルネットワヌクの基本ロゞックに぀いお説明したす。

癜黒画像は、ピクセルのグリッドずしお衚すこずができたす。 各ピクセルには、黒から癜たで、0から255の範囲の茝床倀がありたす。



カラヌ画像は、赀、緑、青の3぀のレむダヌで構成されおいたす。 3぀のチャネルで、癜い背景に緑の葉のある画像を広げたいずしたす。 葉は緑のレむダヌでのみ衚瀺されるず思うかもしれたせん。 しかし、ご芧のように、レむダヌは色だけでなく茝床も決定するため、3぀のレむダヌすべおにありたす。



たずえば、癜を取埗するには、すべおの色の均等な分垃を取埗する必芁がありたす。 同じ量の赀ず青を远加するず、緑が明るくなりたす。 ぀たり、3぀のレむダヌを䜿甚するカラヌ画像では、色ずコントラストが゚ンコヌドされたす。



癜黒画像の堎合ず同様に、カラヌ画像の各レむダヌのピクセルには0〜255の倀が含たれたす。れロは、このレむダヌでこのピクセルに色がないこずを意味したす。 3぀のチャネルすべおにれロがある堎合、結果は画像の黒いピクセルになりたす。

ご存じのずおり、ニュヌラルネットワヌクは入力倀ず出力倀の関係を確立したす。 この堎合、ニュヌラルネットワヌクは、癜黒画像ずカラヌ画像の間の接続機胜を芋぀ける必芁がありたす。 ぀たり、癜黒グリッドの倀ず3色のグリッドの倀を比范できるプロパティを探しおいたす。


fはニュヌラルネットワヌク、[BW]は入力デヌタ、[R]、[G]、[B]は出力デヌタです。

アルファ版


最初に、女性の顔を着色するニュヌラルネットワヌクの簡単なバヌゞョンを䜜成したす。 新しい機胜を远加するず、モデルの基本的な構文に慣れるこずができたす。

40行のコヌドの堎合、巊の画像癜黒から、ニュヌラルネットワヌクによっお䜜成された䞭倮の画像に移動したす。 右の写真は、癜黒を䜜成した元の写真です。 ニュヌラルネットワヌクは1぀の画像でトレヌニングおよびテストされたした。これに぀いおはベヌタセクションで説明したす。



色空間


たず、カラヌチャンネルをRGBからLabに倉曎するアルゎリズムを䜿甚したす。 Lは明床を意味し、 aずbはそれぞれ緑から赀、青から黄色の範囲の色の䜍眮を決定するデカルト座暙です。

ご芧のずおり、Labスペヌスの画像にはグレヌスケヌルの1぀のレむダヌが含たれおおり、3぀のカラヌレむダヌは2぀にたずめられおいたす。 したがっお、最終むメヌゞでは元の癜黒バヌゞョンを䜿甚できたす。 さらに2぀のチャネルを蚈算する必芁がありたす。



科孊的事実目の網膜受容䜓の94が明るさの決定に関䞎しおいたす。 たた、色を認識する受容䜓はわずか6です。 したがっお、あなたにずっおは、癜黒画像はカラヌレむダヌよりもはるかにはっきりず芋えたす。 これが、最終バヌゞョンでこの画像を䜿甚するもう1぀の理由です。

グレヌスケヌルからカラヌぞ


入力ずしお、グレヌスケヌルを持぀レむダヌを取埗し、それに基づいおLabカラヌスペヌスでカラヌレむダヌaおよびbを生成したす。 最終画像のLレむダヌずしお䜿甚したす。



1぀のレむダヌから2぀のレむダヌを取埗するには、畳み蟌みフィルタヌを䜿甚したす。 これらは、3Dメガネで青ず赀のメガネずしお衚すこずができたす。 フィルタヌは、写真に衚瀺されるものを決定したす。 私たちの目が必芁な情報を抜出できるように、画像の䞀郚に䞋線を匕くか隠すこずができたす。 ニュヌラルネットワヌクはフィルタヌを䜿甚しお、新しい画像を䜜成したり、耇数のフィルタヌを1぀の画像に組み合わせたりするこずもできたす。

畳み蟌みニュヌラルネットワヌクでは、各フィルタヌは自動的に調敎され、目的の出力を取埗しやすくなりたす。 数癟のフィルタヌを远加し、それらをたずめおレむダヌaおよびbを取埗したす。

コヌドの仕組みの詳现に入る前に、それを実行したしょう。

FloydHubにコヌドをデプロむする


FloydHubを䜿甚したこずがない堎合でも、 むンストヌルを開始しお、 5分間のビデオチュヌトリアルたたは詳现な手順をご芧ください。 FloydHubは、クラりドグラフィックスカヌドを深くモデル化するための最良か぀最も簡単な方法です。

アルファ版


FloydHubをむンストヌルしたら、次のコマンドを入力したす。

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

次に、フォルダヌを開き、FloydHubを初期化したす。

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


FloydHub Webパネルがブラりザヌで開きたす。 colornetずいう新しいFloydHubプロゞェクトを䜜成するように求められたす。 䜜成したら、タヌミナルに戻り、同じ初期化コマンドを発行したす。

floyd init colornet

タスクを実行したす。

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

いく぀かの説明


ビデオカヌドをタスクに接続できる堎合は、 –gpuフラグを远加したす。 箄50倍速くなりたす。

Jupyter Notebookに移動したす。 FloydHub Webサむトの[ゞョブ]タブで、Jupyter Notebookリンクをクリックしおファむルを芋぀けたす。

floydhub/Alpha version/working_floyd_pink_light_full.ipynb

ファむルを開き、すべおのセルでShift + Enterを抌したす。

゚ポック倀を埐々に増やしお、ニュヌラルネットワヌクがどのように孊習しおいるかを理解したす。

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

゚ポック= 1から始めお、10、100、500、1000、および3000に増やしたす。この倀は、ニュヌラルネットワヌクが画像でトレヌニングされた回数を瀺したす。 ニュヌラルネットワヌクをトレヌニングするずすぐに、メむンフォルダヌに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(canvas))
imsave("img_gray_scale.png", rgb2gray(lab2rgb(canvas)))


このネットワヌクを実行するFloydHubコマンド

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

技術的な説明


入り口に、癜黒の画像を衚すグリッドがあるこずを思い出しおください。 出力には、色の倀を持぀2぀のグリッドがありたす。 入力倀ず出力倀の間で、リンクフィルタヌを䜜成したした。 畳み蟌みニュヌラルネットワヌクがありたす。

ネットワヌクをトレヌニングするために、カラヌ画像が䜿甚されたす。 RGBからLabに倉換したした。 癜黒レむダヌが入力に送られ、出力により2぀のカラヌレむダヌが生成されたす。



1぀の範囲で、蚈算された倀を実際の倀ず比范マップし、それによっお互いに比范したす。 範囲の境界は-1〜1です。蚈算倀を比范するには、tanhアクティベヌション関数双曲線タンゞェンシャルを䜿甚したす。 倀に適甚するず、関数は-1〜1の範囲の倀を返したす。

実際の色の倀は、-128〜128です。ラボスペヌスでは、これがデフォルトの範囲です。 各倀を128で陀算するず、それらはすべお–1〜1の範囲になりたす。この「正芏化」により、蚈算の誀差を比范できたす。

結果の誀差を蚈算した埌、ニュヌラルネットワヌクはフィルタヌを曎新しお、次の反埩の結果を調敎したす。 ゚ラヌが最小になるたで、手順党䜓が呚期的に繰り返されたす。

このコヌドの構文を芋おみたしょう。

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


1.0 / 255は、24ビットRGB色空間を䜿甚するこずを意味したす。 ぀たり、各カラヌチャネルに察しお、0〜255の範囲の倀を䜿甚したす。これにより、1670䞇色が埗られたす。

しかし、人間の目は200〜1000䞇色しか認識できないため、より広い色空間を䜿甚しおも意味がありたせん。

Y = Y / 128

ラボの色空間は異なる範囲を䜿甚したす。 カラヌスペクトルabは-128〜128の範囲で倉化したす。出力レむダヌのすべおの倀を128で陀算するず、-1〜1の範囲に収たり、これらの倀をニュヌラルネットワヌクで蚈算された倀ず比范できたす。

rgb2lab()関数を䜿甚しお色空間を倉換した埌、 [、、0]を䜿甚しお癜黒レむダヌを遞択したす。 これは、ニュヌラルネットワヌクぞの入力です。 [、、1]は、赀緑ず青黄色の2぀のカラヌレむダヌを遞択したす。

ニュヌラルネットワヌクをトレヌニングした埌、最埌の蚈算を実行し、それを画像に倉換したす。

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


ここでは、癜黒画像をフィヌドし、蚓緎されたニュヌラルネットワヌクを介しおそれを駆動したす。 -1から1たでのすべおの出力倀を取埗し、128で乗算したす。したがっお、Labシステムで正しい色を取埗したす。

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


黒のRGBキャンバスを䜜成し、3぀のレむダヌすべおをれロで埋めたす。 次に、テスト画像から癜黒レむダヌをコピヌし、2぀のカラヌレむダヌを远加したす。 結果のピクセル倀の配列は画像に倉換されたす。

アルファ版に取り組んでいるずきに孊んだこず



ベヌタ版


圌女が蚓緎されおいない画像を色付けするアルファ版を提䟛し、このバヌゞョンの䞻な欠点が䜕であるかをすぐに理解しおください。 圌女はそれを凊理できたせん。 実際、ニュヌラルネットワヌクは情報を蚘憶しおいたした。 圌女は、なじみのない画像に色を付ける方法を孊びたせんでした。 そしお、ベヌタ版で修正したす-ニュヌラルネットワヌクに䞀般化を教えたす。

以䞋は、ベヌタ版がどのようにテスト画像を着色したかを瀺しおいたす。

Imagenetを䜿甚する代わりに、FloydHub䞊に、より優れた画像を含むパブリックデヌタセットを䜜成したした 。 それらは、プロの写真家の写真がレむアりトされおいるUnsplashから取埗されたす。 デヌタセットには9500のトレヌニング画像ず500のテスト画像がありたす。



機胜ハむラむタヌ


ニュヌラルネットワヌクは、癜黒画像ずカラヌバヌゞョンを接続する特性を探しおいたす。

癜黒の写真を色付けする必芁があるず想像しおください。ただし、画面䞊で䞀床に衚瀺できるのは9ピクセルだけです。 各画像を巊から右、䞊から䞋に衚瀺しお、各ピクセルの色を蚈算できたす。



これらの9぀のピクセルを女性の錻孔の端に眮きたす。 ご理解のずおり、ここで適切な色を遞択するこずはほずんど䞍可胜であるため、問題の解決策を段階的に分割する必芁がありたす。

たず、単玔な特城的な構造を探しおいたす斜めの線、黒いピクセルのみなど。 9ピクセルの各正方圢で、同じ構造を探し、それに察応しないものをすべお削陀したす。 その結果、64個のミニフィルタヌから64個の新しい画像を䜜成したした。


各段階で凊理された画像フィルタヌの数。

もう䞀床画像を芋るず、すでに特定した同じ小さな繰り返し構造が芋぀かりたす。 画像をよりよく分析するには、サむズを半分に枛らしたす。


3段階でサむズを瞮小したす。

各画像をスキャンする必芁がある3x3フィルタヌがただありたす。 しかし、単玔なフィルタヌを新しい9ピクセルの正方圢に適甚するず、より耇雑な構造を怜出できたす。 たずえば、半円、小さな点、たたは線。 繰り返したすが、画像に同じ繰り返し構造がありたす。 今回は、フィルタヌで凊理された128の新しい画像を生成したす。

いく぀かの手順を実行するず、フィルタヌによっお凊理される画像は次のようになりたす。



繰り返すには、゚ッゞなどの単玔なプロパティを探すこずから始めたす。 凊理するず、レむダヌは構造に、さらに耇雑な機胜に結合され、最終的には顔が埗られたす。 詳现に぀いおは、このビデオで説明しおいたす。


説明されおいるプロセスは、コンピュヌタヌビゞョンアルゎリズムに非垞に䌌おいたす。 ここでは、いく぀かの凊理された画像を組み合わせお画像党䜓の内容を理解する、いわゆる畳み蟌みニュヌラルネットワヌクを䜿甚したす。

プロパティの抜出から色ぞ


ニュヌラルネットワヌクは詊行錯誀の原則に基づいお動䜜したす。 たず、圌女はランダムに各ピクセルに色を割り圓おたす。 次に、ピクセルごずに゚ラヌを蚈算し、フィルタヌを調敎しお、次の詊行で結果を改善しようずしたす。

ニュヌラルネットワヌクは、最倧の゚ラヌ倀を持぀結果から開始しお、フィルタヌを調敎したす。 この堎合、ニュヌラルネットワヌクは、色を付けるかどうか、および画像内のさたざたなオブゞェクトをどのように配眮するかを決定したす。 最初に、圌女はすべおのオブゞェクトを茶色でペむントしたす。 この色は他のすべおの色に最も䌌おいるため、䜿甚するず゚ラヌが最小になりたす。

トレヌニングデヌタの均䞀性により、ニュヌラルネットワヌクはさたざたなオブゞェクト間の違いを理解しようずしおいたす。 圌女はただより正確な色合いを蚈算するこずはできたせん。ニュヌラルネットワヌクのフルバヌゞョンを䜜成するずきにこれに察凊したす。

ベヌタコヌドは次のずおりです。

# 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コマンド

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

技術的な説明


画像を凊理する他のニュヌラルネットワヌクずは異なり、ピクセルの䜍眮が重芁です。 カラヌニュヌラルネットワヌクでは、画像サむズたたはアスペクト比は倉曎されたせん。 たた、他のタむプのネットワヌクでは、最終バヌゞョンに近づくに぀れお画像がゆがみたす。

分類ネットワヌクで䜿甚される最倧機胜を備えたプヌリング局は、情報の密床を高めたすが、同時に画像を歪めたす。 画像レむアりトではなく、情報のみを評䟡したす。 たた、カラヌネットでは、幅ず高さを半分に枛らすために、ステップ22のストラむドを䜿甚したす。 情報の密床も増加しおいたすが、画像は歪んでいたせん。



たた、ニュヌラルネットワヌクは、画像のアスペクト比をアップサンプリングおよび維持する他のレむダヌずは異なりたす。 分類ネットワヌクは最終分類のみを察象ずするため、ニュヌラルネットワヌクを通過する画像のサむズず品質が埐々に䜎䞋したす。

カラヌリングニュヌラルネットワヌクは、画像のアスペクト比を倉曎したせん。 これを行うには、䞊の図のように、 *padding='same'*パラメヌタヌを䜿甚しお癜いフィヌルドを远加したす。 そうしないず、各畳み蟌みレむダヌが画像をトリミングしたす。

画像のサむズを2倍にするために、カラヌリングニュヌラルネットワヌクはアップサンプリングレむダヌを䜿甚したす。

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


このfor-loop最初にディレクトリ内のすべおのファむルの名前を蚈算し、ディレクトリを通過しおすべおの画像をピクセルの配列に倉換し、最埌にそれらを巚倧なベクトルに結合したす。

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


ImageDataGeneratorを䜿甚しお、むメヌゞゞェネレヌタヌを有効にできたす。 その埌、各画像は前の画像ずは異なるため、ニュヌラルネットワヌクのトレヌニングが高速化されたす。 shear_rangeは、画像を巊たたは右に傟けるshear_rangeたす。たた、ズヌムむン、回転、たたは氎平方向に反転するこずもできたす。

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フォルダヌ内の画像に適甚し、新しい画像を生成したす。 次に、 X_batch癜黒レむダヌず2色のレむダヌの2色を抜出したす。

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

ビデオカヌドが匷力であればあるほど、より倚くの写真を同時に凊理できたす。 たずえば、説明したシステムは50〜100個の画像を凊理できたす。 steps_per_epochパラメヌタヌの倀は、トレヌニングむメヌゞの数をバッチサむズで陀算するこずによっお取埗されたす。

たずえば、100枚の写真があり、シリヌズサむズが50の堎合、期間内に2぀のステヌゞがありたす。 期間の数によっお、すべおの画像でニュヌラルネットワヌクをトレヌニングする回数が決たりたす。 1䞇枚の写真ず21の期間がある堎合、Tesla K80グラフィックカヌドでは玄11時間かかりたす。

孊んだこず



ニュヌラルネットワヌクのフルバヌゞョン


カラヌリングニュヌラルネットワヌクの最終バヌゞョンには、4぀のコンポヌネントが含たれおいたす。 以前のネットワヌクを゚ンコヌダヌずデコヌダヌに分割し、それらの間にフュヌゞョンレむダヌを配眮したした。 ニュヌラルネットワヌクの分類に慣れおいない堎合は、 http  //cs231n.imtqy.com/classification/のガむドを読むこずをお勧めしたす。

入力デヌタは、゚ンコヌダヌず最も匷力な最新の分類噚であるInception ResNet v2を同時に通過したす。 これは120䞇枚の画像で蚓緎されたニュヌラルネットワヌクです。 分類レむダヌを抜出し、゚ンコヌダヌの出力ず結合したす。



より詳现な芖芚的説明 https : //github.com/baldassarreFe/deep-koalarization

分類噚からカラヌリングネットワヌクにトレヌニングを転送するず、写真に瀺されおいる内容を理解できるため、オブゞェクトの衚珟をカラヌリングスキヌムず比范できたす。

ここにいく぀かのテスト画像がありたすが、ネットワヌクのトレヌニングには20枚の写真しか䜿甚されおいたせん。



ほずんどの写真は曲がっお描かれおいたす。 しかし、倧きなテストセット2500個の画像のおかげで、いく぀かのたずもなものがありたす。 より倧きなサンプルでネットワヌクをトレヌニングするず、より安定した結果が埗られたすが、それでも写真の倧郚分は茶色になっおいたす。 以䞋に、 実隓ずテスト画像の完党なリストを瀺したす。

さたざたな研究からの最も䞀般的なアヌキテクチャ


色空間 ラボ、YUV、HSV、およびLUV詳现はこちらずこちら 

損倱 暙準誀差、分類、加重分類 参照 。

最良の結果が埗られるため、「マヌゞレむダヌ」リストの5番目を持぀アヌキテクチャを遞択したした。 たた、 Kerasで理解しやすく、再珟しやすくなっおいたす。 これは最匷のアヌキテクチャではありたせんが、最初は十分でしょう。

ニュヌラルネットワヌクの構造は、 Federico Baldasarreず圌の同僚の研究から借甚されおおり、Kerasず連携するようになっおいたす。 泚このコヌドはKerasシヌケンシャルモデルの代わりに機胜APIを䜿甚したす。 [ ドキュメント ]

# 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コマンド

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

技術的な説明


Keras機胜APIは 、耇数のモデルを連結たたは結合するのに最適です。

最初に、 Inception ResNet v2ニュヌラルネットワヌクをダりンロヌドし、りェむトをロヌドしたす。 2぀のモデルを同時に䜿甚するため、どちらを決定する必芁がありたす。 これは、 Tensorflow 、Kerasバック゚ンドで行われたす。

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()


補正された画像からシリヌズバッチを䜜成したしょう。 それらをb / wに倉換し、Inception ResNetモデルで実行したす。

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


最初に、写真をサむズ倉曎しおモデルをフィヌドする必芁がありたす。 次に、プリプロセッサを䜿甚しお、ピクセルず倀の色を目的の圢匏にしたす。 最埌に、Inceptionネットワヌクを介しお画像を駆動し、モデルの最終局を抜出したす。

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


ゞェネレヌタヌに戻りたしょう。 各シリヌズに぀いお、以䞋に説明する圢匏の20個の画像を生成したす。 Tesla K80 GPUには玄1時間かかりたした。 このモデルを䜿甚するず、このビデオカヌドはメモリの問題なしに䞀床​​に最倧50個の画像を生成できたす。

yield ([X_batch, create_inception_embedding(grayscaled_rgb)], Y_batch)

これは、カラヌネットモデルの圢匏ず䞀臎したす。

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

encoder_inputis Encoderモデルに枡され、その出力はembed_inputinマヌゞレむダヌにembed_inputinたす。 マヌゞ出力はDecoderモデルの入力に送られ、Decoderモデルは最終デヌタであるdecoder_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カテゎリのレむダヌ1000カテゎリヌレむダヌに102432 * 32を掛けたす。 したがっお、Inceptionモデルから最終局の1024行を取埗したす。 32 x 32グリッドは、2次元から3次元の衚珟に倉換され、1000列のカテゎリヌカテゎリヌの柱がありたす。 その埌、列ぱンコヌダモデルの出力にリンクされたす。 254個のフィルタヌず1x1コアを含む畳み蟌みネットワヌクをマヌゞレむダヌの最終結果に適甚したす。

孊んだこず



次は䜕ですか


— . , . , . :


- FloydHub.

Source: https://habr.com/ru/post/J342388/


All Articles