[cycleGAN]ゾンビランドサガ の水野愛を生き返らせる

[ゾンビランドサガ](https://zombielandsaga.com/#index)というアニメの水野愛(以下、愛ちゃん)がクッソ可愛い。
ゾンビの姿の愛ちゃんも可愛らしいですが、やっぱり生前の愛ちゃんの方が可愛い。
そこで、[cycleGAN](https://junyanz.github.io/CycleGAN/)を使って、ゾンビ愛ちゃんと生前愛ちゃんのデータセットから変換してみようと思います。


docker + pytorchの作成済みモデルを利用してお手軽に実装します。
また、**ローカルにnvidia-dockerの環境が構築されている前提**です。
データに関しては、１話〜６話までの画像から愛ちゃんを手作業で検出し、データセットを作成しました。
データセットの公開予定はありません。

画像数

| ep | ゾンビ | 生前 |
| :------ | -----: | ---: |
| opening       |    3 |  84 |
| 1       |     34 |  369 |
| 2       |    312 |  503 |
| 3       |    261 |  643 |
| 4       |     97 |  490 |
| 5       |    104 |  455 |
| 6       |    115 |  398 |
| Sum     | 926 | 2942 |




## 手順

### 1. [pytorch/pytorch](https://hub.docker.com/r/pytorch/pytorch/)のイメージからコンテナを作成

`docker pull pytorch/pytorch`
`nvidia-docker run -it --name aichanmajiangel -p 8097:8097 pytorch/pytorch`

GPUを使うため`nvidia-docker`を使う。
`visdom.server`がデフォルトで`8097`に立つのでポートを開放しておく。
再接続する場合は`nvidia-docker exec -it aichanmajiangel bash`



### 2. [pytorch-CycleGAN-and-pix2pix](https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix)をcloneする

`git clone https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix.git`
`cd pytorch-CycleGAN-and-pix2pix`
`pip install -r requirements.txt`



###  3. データセットの用意

#### a. 気合と根気で集めます。

```python
import kiai
import konki
from os import path
from PIL import Image

images_path = 'aichan_image/'
for i in range(konki.max()):
	image = kiai.get('水野愛')
    if zombie:
        image.save(path.join(images_path,
                     'zombie',
                     'zombie_{}.png'.format(str(i).zfill(5))))
    else:
	    image.save(path.join(images_path,
                     'aichan',
                     'aichan_{}.png'.format(str(i).zfill(5))))
```

#### b. trainとtestにスプリットする。

```python
import os
import shutil
import random

images_path = 'aichan_image/'
zombie = os.listdir(path.join(images_path, 'zombie'))
aichan = os.listdir(path.join(images_path, 'aichan'))

# random shuffle
zombie = random.sample(zombie, len(zombie))
aichan = random.sample(aichan, len(aichan))
# zombe[0]   -> 'xxxx.png'
# len(zombi) ->  917

# split 9:1
trainA = zombie[:int(len(zombie)/10*9)]
testA = zombie[int(len(zombie)/10*9):]
trainB = aichan[:int(len(aichan)/10*9)]
testB = aichan[int(len(aichan)/10*9):]

# create dataset
if not os.path.exists('dataset'):
    os.makedirs('dataset')
    os.makedirs('dataset/trainA')
    os.makedirs('dataset/trainB')
    os.makedirs('dataset/testA')
    os.makedirs('dataset/testB')

for c, n in zip([trainA, testA, trainB, testB], ['trainA', 'testA', 'trainB', 'testB']):
    for i,image in enumerate(c):
        shutil.copy(image, path.join('dataset',n))
```

#### c. コンテナの`/workspace/pytorch-CycleGAN-and-pix2pix/datasets`に配置する

`docker cp dataset [CONTAINER_ID]:/workspace/pytorch-CycleGAN-and-pix2pix/datasets`

`mv workspace/pytorch-CycleGAN-and-pix2pix/datasets workspace/pytorch-CycleGAN-and-pix2pix/aichan_images`



### 4. 学習

`python -m visdom.server & `

`python train.py --dataroot ./datasets/aichan_images --name aichan_cyclegan --model cycle_gan`

特にオプションを指定しない場合、GTX1080なら1日で学習が終わる。



### 5. 変換

`python test.py --dataroot ./datasets/aichan_images --name aichan_cyclegan --model cycle_gan`





## 結果

`/workspace/pytorch-CycleGAN-and-pix2pix/results/aichan_cyclegan/test_latest`直下の`index.html`か`images`ディレクトリから確認できる。

中でもよかったやつ [元の画像:生成画像]

![img_001239002.png](https://qiita-image-store.s3.amazonaws.com/0/197110/6808713f-493d-c45e-6ecc-f90403ea25cf.png)
![img_002988001.png](https://qiita-image-store.s3.amazonaws.com/0/197110/7a09bf04-d281-d34e-b78e-8f0ac1c279ad.png)
![img_005088002.png](https://qiita-image-store.s3.amazonaws.com/0/197110/76e0a591-672e-c001-14fc-60294ae4d74d.png)
![img_007765000.png](https://qiita-image-store.s3.amazonaws.com/0/197110/aa4036cc-202c-ee35-50f6-847a3b81be3f.png)

逆に悪いのだとこんな感じ。
![img_001808000.png](https://qiita-image-store.s3.amazonaws.com/0/197110/ed799bd3-59d6-2b0c-ae8e-f5cb1c8425c2.png)
![img_001565003.png](https://qiita-image-store.s3.amazonaws.com/0/197110/9008ab15-f737-b6cc-6863-b3797ad3272b.png)
![img_007619000.png](https://qiita-image-store.s3.amazonaws.com/0/197110/722a1647-83f5-0965-712e-b7f44c07da59.png)
![img_000378003.png](https://qiita-image-store.s3.amazonaws.com/0/197110/ab8e33d8-ba8d-1159-2db2-533c0656b72d.png)

**試しに３話までデータの50epochで回した際には顔の包帯を全く消せてなかったので、少しは手応えがある結果になってきた。**
また、さくら達も上手く変換できている画像が見られたのが面白かった。
※愛ちゃんが写っている画像の端に写っている程度の別のキャラクター



#### 全体的に水色にされがちな傾向が伺えた。

-> 愛ちゃんの顔まわりの画像に限定したため、服の色が大きく影響を与えた？
カラフルにされるのはOPも学習データに加えたので影響を受けてそう。



#### 作画が違うと厳しい。

-> 絶叫時の愛ちゃんや、焼肉を食べている愛ちゃんの変換が厳しそう。

この量のデータでここまで変換できるとは思わなかった。
モデルに手を加える技術力を私は持ち得ないため、この結果からデータセットに手を加えてより上手く変換出来るようにしてみたい。


## まとめ

巽幸太郎の技術ちからはすごい・・