LoginSignup
50
43

More than 5 years have passed since last update.

ディープラーニングで落書きを消す

Last updated at Posted at 2017-10-14

ディープラーニングで落書きを消す

先日畳み込みオートエンコーダでノイズ除去を行いましたが、そのときの課題は再現された画像が滲んでしまっていたことです。

今回はもう少し改良して、オートエンコーダやCNNで落書きを消してみようと思います。
ライブラリにはKerasを使います。

データセットはCifar10を使います。
Cifar10にランダムに棒線で落書きします。
棒線の色は黒バージョンとランダム色バージョンを作りました。

黒バージョン

4.PNG

ランダム色バージョン

5.PNG

この棒線を消して元画像を再現するよう、ディープラーニングで学習します。
トレーニングデータ50,000点の落書き除去を学習し、テストデータ10,000点の落書き除去&元画像再現性を評価します。
再現性の評価関数はmean squared errorを使います。

落書きを消す手法として、オートエンコーダとCNNを試しました。
試した手法:
1. 畳み込みオートエンコーダ
2. 畳み込みオートエンコーダ改良版
3. DNCNN
4. Win5-RB

コードは以下にあります。
https://github.com/shibuiwilliam/DeepLearningDenoise

畳み込みオートエンコーダ

前回同様の畳み込みオートエンコーダです。

0.png

レイヤー定義

# encoder
input_img = Input(shape=(32, 32, 3))
x = Conv2D(32, (3, 3), padding='same')(input_img)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = MaxPooling2D((2, 2), padding='same')(x)
x = Conv2D(32, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
encoded = MaxPooling2D((2, 2), padding='same')(x)

# decoder
x = Conv2D(32, (3, 3), padding='same')(encoded)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(32, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = UpSampling2D((2, 2))(x)
x = Conv2D(3, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
decoded = Activation('sigmoid')(x)

# compile
model = Model(input_img, decoded)
model.compile(optimizer='adam', loss='mean_squared_error')

# options
es_cb = EarlyStopping(monitor='val_loss', patience=2, verbose=1, mode='auto')
chkpt = saveDir + 'AutoEncoder_Cifar10_deline_weights.{epoch:02d}-{loss:.2f}-{val_loss:.2f}.hdf5'
cp_cb = ModelCheckpoint(filepath = chkpt, monitor='val_loss', verbose=1, save_best_only=True, mode='auto')

# train
history = model.fit(x_train_line, x_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test_line, x_test),
                    callbacks=[es_cb, cp_cb],
                    shuffle=True)

黒バージョンもランダム色バージョンも、やはり滲んでしまいます。
結果(黒バージョン)
mean squred error: 0.00251344182827

ae1.PNG
ae2.PNG

結果(ランダム色バージョン)
mean squred error: 0.00406358846352

aeColor1.PNG
aeColor2.PNG

畳み込みオートエンコーダ改良版

畳み込みオートエンコーダを改良しました。こちらはエンコーダ・デコーダの間を全結合に変換して接続します。

1.png

レイヤー定義


# encoder
input_img = Input(shape=(32, 32, 3))
x = Conv2D(32, (3, 3), padding='same')(input_img)
x = BatchNormalization()(x)
x = Activation('elu')(x)
x = Conv2D(32, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
x = Activation('elu')(x)
x = Conv2D(32, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
x = Activation('elu')(x)
x = Flatten()(x)
x = Dense(3072)(x)
x = BatchNormalization()(x)
encoded = Activation('sigmoid')(x)

# decoder
x = Dense(3072)(encoded)
x = BatchNormalization()(x)
x = Activation('elu')(x)
x = Reshape((32,32,3))(x)
x = Conv2D(32, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
x = Activation('elu')(x)
x = Conv2D(32, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
x = Activation('elu')(x)
x = Conv2D(3, (3, 3), padding='same')(x)
x = BatchNormalization()(x)
decoded = Activation('sigmoid')(x)

# compile
model = Model(input_img, decoded)
model.compile(optimizer='adam', loss='mean_squared_error')

# options
es_cb = EarlyStopping(monitor='val_loss', patience=3, verbose=1, mode='auto')
chkpt = saveDir + 'AutoEncoder_Cifar10_delineBlack_CAE_weights.{epoch:02d}-{loss:.2f}-{val_loss:.2f}.hdf5'
cp_cb = ModelCheckpoint(filepath = chkpt, monitor='val_loss', verbose=1, save_best_only=True, mode='auto')

# train
history = model.fit(x_train_line, x_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test_line, x_test),
                    callbacks=[es_cb, cp_cb],
                    shuffle=True)

こうするだけでも意外と再現性が向上するようです。
結果(黒バージョン)
mean squred error: 0.00139122980386

cae2.PNG
cae1.PNG

結果(ランダム色バージョン)
mean squred error: 0.00257390149683

caeColor1.PNG
caeColor2.PNG

多少滲んでしますが、前の畳み込みオートエンコーダよりはきれいに再現できています。

DNCNN

DNCNNはDenoising Convolutional Neural Network(ノイズ除去畳み込みニューラルネットワーク)という、その名のとおりのノイズ除去を目的としたCNNです。
https://arxiv.org/pdf/1608.03981v1.pdf
構造は以下のようなものです。

2.png

畳み込みとBatchNormalization、活性化関数Reluを重ねていき、最後の層だけ活性化関数Tanhを使います。
中間層が16層と厚い構成です。

レイヤー定義

# DNCNN
input_img = Input(shape=(32, 32, 3))
x = Conv2D(64, (3, 3), padding='same')(input_img)
x = Activation('relu')(x)

for i in range(15):
    x = Conv2D(64, (3, 3), padding='same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)

x = Conv2D(3, (3, 3), padding='same')(x)
output_img = Activation('tanh')(x)

# compile
model = Model(input_img, output_img)
model.compile(optimizer='adam', loss='mean_squared_error')

# options
es_cb = EarlyStopping(monitor='val_loss', patience=2, verbose=1, mode='auto')
chkpt = saveDir + 'AutoEncoder_Cifar10_dncnn_weights.{epoch:02d}-{loss:.2f}-{val_loss:.2f}.hdf5'
cp_cb = ModelCheckpoint(filepath = chkpt, monitor='val_loss', verbose=1, save_best_only=True, mode='auto')

# train
history = model.fit(x_train_line, x_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test_line, x_test),
                    callbacks=[es_cb, cp_cb],
                    shuffle=True)

結果は以下のとおりで、大分きれいに落書きが消えて、画像も再現できています。
結果(黒バージョン)
mean squred error: 0.000638661881443

dncnn1.PNG
dncnn2.PNG

結果(ランダム色バージョン)
mean squared error: 0.000755158919282

dncnnColor1.PNG
dncnnColor2.PNG

ところどころ別のノイズが入ってしまっているのが難点です。

Win5-RB

Win5-RBはDNCNNをResnetにしたものです。
Win5-RBはWide Inference Network(Win)が5層構成で、Resnet(R)とBatchNormalization(B)を使っているという意味です。
https://arxiv.org/pdf/1707.05414.pdf

3.png

レイヤー定義

# Win5-RB
input_img = Input(shape=(32, 32, 3))
x = Conv2D(64, (7, 7), padding='same')(input_img)
x = BatchNormalization()(x)
x = Activation('relu')(x)

for i in range(3):
    x = Conv2D(64, (7, 7), padding='same')(x)
    x = BatchNormalization()(x)
    x = Activation('relu')(x)

x = Conv2D(3, (7, 7), padding='same')(x)
x = BatchNormalization()(x)
output_img = layers.add([x, input_img])

# compile
model = Model(input_img, output_img)
model.compile(optimizer='adam', loss='mean_squared_error')

# options
es_cb = EarlyStopping(monitor='val_loss', patience=2, verbose=1, mode='auto')
chkpt = saveDir + 'AutoEncoder_Cifar10_win5rb_weights.{epoch:02d}-{loss:.2f}-{val_loss:.2f}.hdf5'
cp_cb = ModelCheckpoint(filepath = chkpt, monitor='val_loss', verbose=1, save_best_only=True, mode='auto')

# train
history = model.fit(x_train_line, x_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose=1,
                    validation_data=(x_test_line, x_test),
                    callbacks=[es_cb, cp_cb],
                    shuffle=True)

評価関数的にはもっとも良い値を出しています。
結果(黒バージョン)
mean squred error: 0.000271678016009

win1.PNG
win2.PNG

結果(ランダム色バージョン)
mean squred error: 0.000558209863212

winColor1.PNG
winColor2.PNG

きれいに再現できていますが、DNCNN同様に違うノイズが入ってしまっています。

どうやらDNCNNもWin5RBも、真っ白い部分や真っ黒い部分にノイズが残ってしまうようです。

最後に

比較のため、それぞれの結果を並べて表示します。

評価関数

黒バージョン ランダム色バージョン 
畳み込みオートエンコーダ 0.00251344182827 0.00406358846352
畳み込みオートエンコーダ改良版 0.00139122980386 0.00257390149683
DNCNN 0.000638661881443 0.000755158919282
Win5-RB 0.000271678016009 0.000558209863212

畳み込みオートエンコーダ

黒バージョン

ae1.PNG
ae2.PNG

ランダム色バージョン

aeColor1.PNG
aeColor2.PNG

畳み込みオートエンコーダ改良版

黒バージョン

cae2.PNG
cae1.PNG

ランダム色バージョン

caeColor1.PNG
caeColor2.PNG

DNCNN

黒バージョン

dncnn1.PNG
dncnn2.PNG

ランダム色バージョン

dncnnColor1.PNG
dncnnColor2.PNG

Win5-RB

黒バージョン

win1.PNG
win2.PNG

ランダム色バージョン

winColor1.PNG
winColor2.PNG

50
43
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
50
43