【論文読み】Image Inpainting for Irregular Holes Using Partial Convolutions

面白そうな論文があったのでまとめてみました．
正直うまく訳せない部分があったり，理解に欠ける部分もあるので，編集リクエストなど出していただけると大変うれしく思います:bow:


## どんな論文？
"Image Inpainting"とは，NVIDIAが公開した写真の欠落した部分を自動修復させる技術．

画面左の写真の石を塗りつぶすと，右側の写真から石が削除され，その場所に地面や木の枝が補完されている．
<img width="1680" alt="Screen Shot 2018-09-15 at 13.56.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/92ba7277-95b4-53d3-c9dc-fb188ff141e7.png">
<img width="1680" alt="Screen Shot 2018-09-15 at 13.56.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/d9a5a217-ea2f-f3cb-4368-b2aee44d1f11.png">

人の目を塗りつぶすと，目が補完されることがわかる．
<img width="1680" alt="Screen Shot 2018-09-15 at 13.57.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/76dd9fab-1d5f-135d-e818-6c1e34b7ece6.png">
<img width="1680" alt="Screen Shot 2018-09-15 at 13.57.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/2779cbd2-dee5-d05b-b8e4-663308a66b35.png">

以下は公式Youtubeのリンクです．
[Research at NVIDIA: AI Reconstructs Photos with Realistic Results - Youtube](https://www.youtube.com/watch?v=gg0F5JjKmhA)

※arXiv，Githubのリンクは一番下にまとめています．

### 既存技術
- 画像の"穴"(上の写真の白く塗りつぶした箇所)に対して，正常なピクセルや，穴の代替値によって調整された畳み込みフィルタを利用した，典型的な畳込みネットワークによって画像修復を図る

### 問題点
- 色が一致しなかったりぼやけたりする問題がある
- 画像の中心付近にある長方形の領域に焦点を当てており，高価な後処理に依存がちで，尚且失敗する可能性もある

### 提案手法
- 不足している領域と元の写真の両方を調べることでピクセルを再構築する方法を学習した．
- その中でPartial Convolution(部分的な畳み込み)を提案する
  - これは，有効なピクセルにのみ条件づけをするために，マスク化され，再度正規化された畳み込みのことである
  - マスク画像を自動的に生成するというメカニズムが含まれ，他の不規則なマスクの生成方法よりも優れている

### コントリビューション
- Image Inpainting(画像修正・補完)
  - どんな形状，サイズのマスクでも、そして画像の四辺端っこに接した穴でさえも、堅実に対応可能
  - マスク部分が大きくなっても精度が急激に低下することが無いため，任意の箇所を高精度で修復可能
- 大規模マスク画像の生成
  - どのような穴があっても修正出来る，かつ追加の後処理は必要としないネットワークが理想．
  - 汎用性の高いものにするために，様々なサイズの不規則マスク画像を用意して学習させる．
  - 不規則な形状の穴でディープラーニングによる画像修復モデルの効果を実証するのは初の例
  - この大規模なマスク画像のデータセットは，一般公開予定．
  - 実験では穴の大きさだけではなく，それが画像の枠に接している場合の影響も調べる．



## Partial Convolutional Layer
不規則なマスク画像を適切に扱うことが出来る層．
出力は欠損の無い領域にのみ依存し，マスク画像を更新するというステップも含んでいる．
少なくとも1つの有効な入力値(=穴でない，つまりマスクされていない箇所の値)で出力を調整出来る場合，その場所のマスクを削除する．
この層が十分な大きさであれば，マスク画像は徐々に縮小され，有効な値のみがfeature mapに残る．

<img width="950" alt="Screen Shot 2018-09-14 at 17.29.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/46563ebc-023d-af3c-46ad-bcef9fa65dcc.png">

引用: [MathiasGruber/PConv-Keras/Step2 - Partial Convolution Layer.ipynb](https://github.com/MathiasGruber/PConv-Keras/blob/master/Step2%20-%20Partial%20Convolution%20Layer.ipynb)



## 既存技術についてもう少し詳しく
これまでは，画像の中心の周辺の短形領域に焦点を当て，高価な処理をして，後処理(=ぼやけた箇所などを修正することだと思われる)に頼っている．
この作業の目的は，不規則に空いてしまっている穴に対して、ロバストな画像修復モデルを作成することと，追加の後処理や，何かと混合するようなことを必要とせずに，画像修復を行うことである．

最近のDeepLearningを使用しない画像修復の手法では，画像の穴を埋めるのに統計的手法(image statistics)を使用する．
**PatchMatch**では，穴を埋めるために，最も適切なパッチを繰り返し検索する．

### メリット
- そこそこの結果が得られる(図1(b)参照)

### デメリット
- 利用可能なimage statisticsによって制限がかかる
- visual semanticsという概念が無い
  - 例えば，図1(b)ではPatchMatchは周囲の影や壁からの画像パッチを使用して欠落した部分をうまく埋めようとするが，semantically-aware approachは，変わりのペイントのパッチを使おうとする(would make use of patches from the painting instead.)

図1(e)(f)に，様々な穴に対して様々な初期値を利用した，典型的な畳込み層を有したU-Netアーキテクチャを使用した例を示す．

<img width="940" alt="Screen Shot 2018-09-13 at 14.10.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/bcc5b167-0d8a-3383-1ca1-0b7764a31713.png">



## 提案モデル
Partial Convolutionの積み重ねと，マスク画像の更新によって画像の修復を行っていく．

### Partial Convolutional Layer
簡潔にするために，Partial Convolutional Layerとマスク画像更新機能をPartial Convolutional Layerとする．
全ての場所で，Partial Convolutional Layerは以下のように定義される．

<img width="728" alt="Screen Shot 2018-09-14 at 17.42.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/4b1e10d7-8030-91af-62cb-76c3882a5893.png">

$W$: 重み
$b$: バイアス
$X$: 現在の畳込みのウィンドウのfeature value(pixels value)
$M$: 対応するバイナリマスク
$1/sum(M)$: スケーリング係数．有効な(マスクされていない)入力の変化量を調整する

Partial Convolutionでは演算の度にマスクを更新する．
この機能は以下の式で表すことが出来，Forward Passの一部として簡単に実装出来る．
入力画像が有効な画素を十分に含んでいれば，最終的に全てのマスクは1になり，画像修正が完了ということになる．

<img width="486" alt="Screen Shot 2018-09-14 at 17.52.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/aeaf165e-5496-79c8-5d32-068a109840c8.png">


### 実装
Partial Convolution層はPyTorchを拡張して実装した(参考にKerasとChainの再現実装のGithub有り)．
画像と同じサイズの(CxHxW)バイナリマスクを定義し，部分畳み込み演算と同じカーネルサイズを持つ，固定畳み込み層を使用してマスク画像の更新する．

画像サイズが512x512の場合，全体の推論にかかる時間は，穴の大きさに関係なく0.23秒であった(NVIDIA V100 GPU)．

### ネットワーク
UNet-likeなアーキテクチャを設計した．

カーネルサイズは7，5，5，3，3，3，3，3．
チャネルサイズは64，128，256，512，512，512，512，512．
デコーダーは8つのアップサンプリング層を含んでいる．

デコーダー内のPartial Convolution層の出力チャネルは512，512，512，512，256，128，64，3．

Partial Convolution層では，画像の境界(=画像の外枠)付近では既存の畳込みは使用せず，マスキングで直接処理する．
よって画像の境界にある修復された内容は，画像の外にある無効な値の影響を受けなくなり，画像は別の穴と判断される．



## 実験
### マスク画像データセット
これまでは画像内に，画像から短形領域をランダムに切り取ることでデータセットを作成してきたが，今回は，[ここ](https://lmb.informatik.uni-freiburg.de/Publications/2010/Bro10e/sundaram_eccv10.pdf)で説明されているように，ビデオの連続した2つのフレーム間のocclusion/dis-occlusion maskの推定方法の結果を参考にランダムな線や任意の形状を持ったマスク画像を作成した．
尚，作成したマスク画像の枚数は以下の通りである．

#### トレーニング用
55,116枚(512x512)
更に，この中からランダムにサンプリングした画像に対して，水増し(拡大，回転，切り取り)を行う．

#### テスト用
24,866枚(512x512)
同じく水増し(拡大，回転，切り取り)を行う．
Global and loccaly consistent image completionなどの既存の方法では画像の境界付近の穴で正しく修復出来ていなかった．
そのためテストセットは，外枠に近い穴がある場合と，無い場合の2つに分割した．
また，マスクの穴のサイズは6種類ある((0.01, 0.1], (0.1, 0.2],
(0.2, 0.3], (0.3, 0.4], (0.4, 0.5], (0.5, 0.6])．
それぞれは境界線の有無に関わらず1000個のマスクが含まれる．

<img width="633" alt="Screen Shot 2018-09-14 at 13.19.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/12a4423b-9579-352e-7321-38a6a9513137.png">


### トレーニング方法
NVIDIA Tesla V100 GPUとcuDNN、PyTorchを使用し，生成されたマスクをImageNet，Places2，CelebA-HQデータセットの画像に適用することによってニューラルネットワークを訓練します．

トレーニングの期間は，ImageNetとPlaces2は10日，CelebA-HQは3日間であった．


## 実験結果
以下の4つの方法を用いて比較していく．

|方法|説明文|
|:--|:--|
|PM|PatchMatch．最先端の非学習ベースのアプローチ|
|GL|Global and loccaly consistent image completion．Izukaらによって提案された方法|
|GntIpt|Generative image inpainting with contextual attention．Yuらによって提案された方法|
|Conv|ネットワーク構造は今回提案するものと同じだが，典型的な畳込み層を使用する方法|

評価画像は12,000枚で，無作為にマスク画像を当てはめる．
GTは正解画像(Ground Truth)．

### ImageNet
<img width="746" alt="Screen Shot 2018-09-14 at 13.34.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/9c5e8040-dbdd-98c5-1ad4-e606c7b0012e.png">

### Places2
<img width="739" alt="Screen Shot 2018-09-14 at 13.35.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/737abfda-0c30-4cc9-af1a-cdb79857169e.png">

### PConvとConvの比較
<img width="1190" alt="Screen Shot 2018-09-15 at 14.28.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/55bc989b-2231-dd4d-82f6-b8db4e94971c.png">

### CelebA-HQ
<img width="938" alt="Screen Shot 2018-09-15 at 14.30.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/77af8032-7b8c-4a72-47f2-77709766a816.png">


### Quantitative comparisons
L1誤差を用いて，定量的な比較を行う．
各列は穴と画像の面積比を表し，Nは境界無し(No border)，Bは境界有りを表す．

PConvは不規則なマスクに対して他のどの方法よりも有効な手段であることがわかる．
<img width="741" alt="Screen Shot 2018-09-14 at 13.52.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/fa798c21-06f0-5708-bc86-259b49eb13d3.png">

### User Study
次は，定量的な評価ではなく，主観的な評価(A/Bテスト)をAmazon Mechanical Turk(MTurk)を用いて行う．
時間制限無し(A)，有り(B)の2種類の実験がある．

- A
  - PConvと他のネットワークによって生成された画像を比較
  - グラフにはPConvの方が好まれた結果を表示している
  - 50%である場合2つの方法が等しいことを表す
  - 1行目は，穴が境界に触れてはならないが，2行目はそれが許されている
-  B
  - 時間は250ms，1000ms，4000msの3種類
  - GTが他の方法より好まれている割合をグラフに示しており，曲線が低いほどよいことを示す
  - 提案手法のPConvは，おおよそ他の手法より良いことを示している

<img width="1162" alt="Screen Shot 2018-09-14 at 14.04.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/130886/b5f118de-6e1d-8b68-8ef7-b5bc4cc49c77.png">



## 参考
### 公式
- arXiv: [Image Inpainting for Irregular Holes Using Partial Convolutions](https://arxiv.org/abs/1804.07723)
- Youtube: [Research at NVIDIA: AI Reconstructs Photos with Realistic Results](https://www.youtube.com/watch?v=gg0F5JjKmhA)

### 再現実装
- Keras: [MathiasGruber/PConv-Keras](https://github.com/MathiasGruber/PConv-Keras)
- Keras: [chuangtc/PConv-Keras](https://github.com/chuangtc/PConv-Keras) 
  - 上のKerasで書かれたものをForkして食べ物の画像を用いてやってみたもの
  - Jupyter上だけでなくコマンドラインを用いて実行できるPythonファイルが入っていて参考になりました
- Chainer: [SeitaroShinagawa/chainer-partial_convolution_image_inpainting](https://github.com/SeitaroShinagawa/chainer-partial_convolution_image_inpainting)