Face Swap Model ToolをMacBook Proで動かしてみた

昨年末に何かの記事で見つけたredditのFace Swap Model Tool(注1)を、MacBook Proで動かしてみた。

- MacBook Pro (Retina, 13-inch, Late 2013)
- Python 3.6.1 |Anaconda custom (x86_64)| (default, May 11 2017, 13:04:09) , pyenvで入れてあった。
 - tensorflow==1.3.0
 - Keras==2.0.8


アジェンダ
1. Face alignment libraryのインストール
2. Face alignment scriptsを動かす
3. Face Swap Model Toolを動かす
4. Merge Faces scriptを動かす

#1. Face alignment libraryのインストール
[Face alignment library](https://github.com/1adrianb/face-alignment)を利用したスクリプトFace alignment scripts based on 1adrianb/face-alignment(注1)を用いるので、まずはこのライブラリをインストールする。

[Installation](https://github.com/1adrianb/face-alignment#installation)を見ながら、必要なものをインストールしていく。

```
$ export CMAKE_PREFIX_PATH="$(dirname $(which conda))/../"
$ conda install numpy pyyaml setuptools cmake cffi
```
pytorchはソースからでなく、http://pytorch.org/ のGet Startedを見てバイナリをインストールする

```
$ conda install pytorch torchvision -c pytorch 
```
Face alignment libraryをgithubからクローン、今回は~/に配置

```
$ git clone https://github.com/1adrianb/face-alignment

Cloning into 'face-alignment'...
remote: Counting objects: 254, done.
remote: Total 254 (delta 0), reused 0 (delta 0), pack-reused 254
Receiving objects: 100% (254/254), 3.45 MiB | 1.36 MiB/s, done.
Resolving deltas: 100% (150/150), done.
Checking connectivity... done.
$ cd face-alignment/
$ ls
Dockerfile		docs			setup.cfg
LICENSE			examples		setup.py
README.md		face_alignment		test
README.rst		requirements.txt	tox.ini
```

とりあえず、インストール

```
$ pip install -r requirements.txt 
```
```
    --  To compile Boost.Python yourself download boost from boost.org and then go into the boost root folder
    --  and run these commands:
    --     ./bootstrap.sh --with-libraries=python
    --     ./b2
    --     sudo ./b2 install
    --  
```

途中で上記の通り、Boostライブラリがいるとか言われるので http://www.boost.org/users/download/ からboost_1_66_0.tar.gzを持ってきて、インストールする。

```
$ cd boost_1_66_0
$ ./bootstrap.sh --with-libraries=python
$ ./b2
```

今度は、fatal error: 'pyconfig.h' file not found とか言われるのでパスを通しとく。(pyenv使ってるので下記)

```
$ export CPLUS_INCLUDE_PATH=$HOME/.pyenv/versions/anaconda3-4.4.0/include/python3.6m
$ sudo ./b2 install
```

気を取り直して、インストール再トライ

```
$ cd ../face-alignment/
$ pip install -r requirements.txt
$ python setup.py install
```

#2. Face alignment scriptsを動かす
上記Face alignment libraryを利用して、対象ディレクトリ内のJPEG画像から、顔部分を見つけて、256x256の画像としてaligngedサブディレクトリを作って保存してくれる。また、元ディレクトリに元画像から抽出した顔画像を作る際のアフィン変換行列をalignments.jsonとして保存

```
[["frame0011.jpg", "aligned/frame0011.jpg", [0.019485288448609677, 0.001986128101705253, -14.306396543625752, -0.001986128101705253, 0.019485288448609677, -3.5522906348250327]],…
```

Face alignment scriptsを[anonymous/align_images.py](https://gist.github.com/anonymous/5832a6fffb8309ac851a29874c3dbb7b)からダウンロード

- align_images.py
- merge_faces.py
- umeyama.py

align_images.pyとumeyama.pyを~/face-alignment/にコピーしておく。

###OpenCV 3のインストール
OpenCV 3+が入ってなかったのでインストールする。

[import cv2 throws Symbol not found: _clock_gettime](http://answers.opencv.org/question/182067/import-cv2-throws-symbol-not-found-_clock_gettime/)の通り、MAC OS X 10.11.6にOpenCVをpip install opencv-pythonでインストールすると、動かなかったので、homebrewでopencv3をインストールする。

```
$ brew update
$ brew install opencv3 --with-python3
```

[OSXでOpenCV3 + python3の環境を作る](https://qiita.com/shim0mura/items/b0ec437206ed3d19d878) 3章を参考に、pyenv経由で動くようにシンボリックリンク貼る。

```
$ mkdir ~/.pyenv/versions/anaconda3-4.4.0/lib/python3.6/site-packages/cv2
$ ln -s /usr/local/Cellar/opencv/3.4.0/lib/python3.6/site-packages/cv2.cpython-36m-darwin.so ~/.pyenv/versions/anaconda3-4.4.0/lib/python3.6/site-packages/cv2/cv2.cpython-36m-darwin.so
```
###Face alignment script実行
顔を含んだ画像のディレクトリを指定してスクリプト実行

```
$ python align_images.py your_image_directory
```

まだ、怒られる。
tqdmが無いので、インストールする。

```
pip install tqdm
```
加えて

```
Traceback (most recent call last):
  File "align_images.py", line 23, in <module>
    FACE_ALIGNMENT = FaceAlignment( LandmarksType._2D, enable_cuda=True, flip_input=False )
…
  File "/Users/kenichi/.pyenv/versions/anaconda3-4.4.0/lib/python3.6/site-packages/torch/cuda/__init__.py", line 55, in _check_driver
    raise AssertionError("Torch not compiled with CUDA enabled")
AssertionError: Torch not compiled with CUDA enabled
```
GPUも無いので、align_images.pyの23行目のenable_cuda=True を enable_cuda=Falseに

AttributeError: module 'cv2' has no attribute 'imread'　とか言われるので
下記のimport cv2をfrom cv2 import cv2に修正しておく。

- ~/face-alignmentalign_images.py
- ~/face-alignment/face_alignment/utils.py

気を取り直して、スクリプト実行すると、対象ディレクトリにalignments.jsonと、alignedサブディレクトリに256x256の顔画像が保存された。

```
$ python align_images.py your_image_directory
$ ls -F your_image_directory/
aligned/			xxxx.jpg
alignments.json			yyyy.jpg
```

#3. Face Swap Model Toolを動かす
[github](https://github.com/joshua-wu/deepfakes_faceswap/)にありますが、学習済みモデルが同梱されている[zipファイル](https://anonfile.com/p7w3m0d5be/face-swap.zip)をダウンロードして動かすのが手っ取り早いです。 以下、~/face-swapとして展開したことを前提に記述します。
Face Alignment with Dlib(注1)参照

~/face-swap/data/にcageディレクトリと、trumpディレクトリがあるので、それぞれに学習対象とする人の顔画像(JPEG, 256x256 pixels)を数百枚程度配置する。Aさんの顔画像数百枚くらいcageディレクトリに、Bさんのはtrumpディレクトリといった感じ。
もちろん顔画像は、上記Face alignment scriptsで作った。

あとは下記実行するだけ

```
python train.py
```

Face alignment scripts同様、下記のimport cv2をfrom cv2 import cv2に修正しておく。

- train.py
- utils.py
- image_augmentation.py

epoch処理ごとにRelease: Face Swap Model Tool(注1)のトップにあるニコラス・ケイジをトランプ大統領の顔にスワップしているような出力画像が更新される。

trump, cageの順にlossを出力、0.3を下回るくらいになるとAさんがBさんに見えてきます。

原理については、[ここ](https://arxiv.org/abs/1706.02932v2)からアイデアを得たそうで、共通のエンコーダと、AさんとBさん用それぞれのデコーダからなる二つのオートエンコーダを二つのイメージセット(Aさん、Bさん)を用いて同時に学習するということのようです。

- Trump Image -> Trump Model (Common encoder + Trump decoder)
- Cage Image -> Cage Model (Common encoder + Cage decoder)

redditのRelease: Face Swap Model Tool(注1)のスレッド中に作者deepfakes氏の簡単な解説(以下引用)があります。
"The trained model are actually two model with a common encoder. Each model will convert an input face to each's target. Notice here that the source faces are the target of another model. When training two model simultaneously, the encoder will learn the common parts in both examples, and the decoders will learn each person's feature. "

#4. Merge Faces scriptを動かす

上記Face alignment scripts内のmerge_faces.py をFace Swap Model Toolをインストールした~/face-swapディレクトリに置き、Face alignment scriptsでalignments.jsonとaligngedサブディレクトリに見つけた顔画像を持つ、対象ディレクトリを指定して実行する。

```
$ python merge_faces.py your_image_directory
$ ls -F your_image_directory
aligned/			xxxx.jpg
alignments.json			yyyy.jpg
merged/
```
mergedディレクトリ内に、元画像を学習モデルでスワップした画像が出来ます(注2)。

注1) 閲覧注意な内容を含むページなので、検索ください。
注2) 参考画像載せたいのですが、著作権/肖像権フリーの画像で学習してないので、考えます。