ゾンビランドサガというアニメの水野愛(以下、愛ちゃん)がクッソ可愛い。
ゾンビの姿の愛ちゃんも可愛らしいですが、やっぱり生前の愛ちゃんの方が可愛い。
そこで、cycleGANを使って、ゾンビ愛ちゃんと生前愛ちゃんのデータセットから変換してみようと思います。
docker + pytorchの作成済みモデルを利用してお手軽に実装します。
また、ローカルにnvidia-dockerの環境が構築されている前提です。
データに関しては、1話〜6話までの画像から愛ちゃんを手作業で検出し、データセットを作成しました。
データセットの公開予定はありません。
画像数
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のイメージからコンテナを作成
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をcloneする
git clone https://github.com/junyanz/pytorch-CycleGAN-and-pix2pix.git
cd pytorch-CycleGAN-and-pix2pix
pip install -r requirements.txt
3. データセットの用意
a. 気合と根気で集めます。
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にスプリットする。
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
ディレクトリから確認できる。
中でもよかったやつ [元の画像:生成画像]
試しに3話までデータの50epochで回した際には顔の包帯を全く消せてなかったので、少しは手応えがある結果になってきた。
また、さくら達も上手く変換できている画像が見られたのが面白かった。
※愛ちゃんが写っている画像の端に写っている程度の別のキャラクター
全体的に水色にされがちな傾向が伺えた。
-> 愛ちゃんの顔まわりの画像に限定したため、服の色が大きく影響を与えた?
カラフルにされるのはOPも学習データに加えたので影響を受けてそう。
作画が違うと厳しい。
-> 絶叫時の愛ちゃんや、焼肉を食べている愛ちゃんの変換が厳しそう。
この量のデータでここまで変換できるとは思わなかった。
モデルに手を加える技術力を私は持ち得ないため、この結果からデータセットに手を加えてより上手く変換出来るようにしてみたい。
まとめ
巽幸太郎の技術ちからはすごい・・