SimSwap で遊んでみました

# 概要

SimSwap という写真の顔を取り替えるプログラムが公開されていたので、インストールして遊んでみました。
OS が Windows なのと Anaconda を入れていないことで少し手間取ったので、手順を共有したいと思います。

# 環境

Windows 10
Python 3.8.1
CUDA Toolkit 10.2
NVIDIA GeForce GTX 1080
GeForce Game Ready ドライバ 456.71

# 手順

### 1. CUDA Toolkit をインストールする

[SimSwap/preparation.md](https://github.com/neuralchen/SimSwap/blob/main/docs/guidance/preparation.md) を見ると CUDA をインストールした方が良さそうなので、バージョンを合わせてインストールします。
上でも書いたとおり私は Anaconda を入れていないので、`conda` ではなくインストーラをダウンロードして入れました。

こちら → [CUDA Toolkit 10.2 Download](https://developer.nvidia.com/cuda-10.2-download-archive?target_os=Windows&target_arch=x86_64&target_version=10&target_type=exelocal)

### 2. git clone する

[SimSwap の GitHub](https://github.com/neuralchen/SimSwap) で URL をコピーして git clone します。

```
> git clone https://github.com/neuralchen/SimSwap.git
```

私が clone した時点では以下のコミットでした。

- [439f6ff - Update README.md](https://github.com/neuralchen/SimSwap/tree/439f6ff94fcbd2e64659dc1c249a1a509bf69836)

### 3. 仮想環境を構築する

```
> python -m venv .venv
> .venv\Scripts\activate
(.venv) >
```

先程の preparation.md を見て、なるべくパッケージのバージョンを合わせるようにインストールしました。
`conda` が使えないことで苦労するのは pytorch のインストールだと思います。
[Start Locally | PyTorch](https://pytorch.org/get-started/locally/) というページで `pip` コマンドを調べられますが、そのまんまだとインストールできなかったので、以下のように変えてみました。

```
(.venv) > pip install torch==1.8.1+cu102 torchvision==0.9.1+cu102 torchaudio==0.8.1 -f https://download.pytorch.org/whl/torch_stable.html
```

CUDA が使えるか確認します。

```
(.venv) > python
>>> import torch
>>> torch.cuda.is_available()
True
>>> exit()
(.venv) >
```

あとは書いてあるとおりインストールしました。

```
(.venv) > pip install insightface==0.2.1 onnxruntime moviepy
```

### 4. preparation のつづき

insightface のモデルをダウンロードして (解凍して) 配置するようにとあるので、そのとおりにします。

> We use the face detection and alignment methods from [insightface](https://github.com/deepinsight/insightface) for image preprocessing. Please download the relative files and unzip them to ./insightface_func/models from this [link](https://onedrive.live.com/?authkey=%21ADJ0aAOSsc90neY&cid=4A83B6B633B029CC&id=4A83B6B633B029CC%215837&parId=4A83B6B633B029CC%215834&action=locate).

(SimSwap の) 学習済みモデルもダウンロードして (解凍して) 配置します。

> There are two archive files in the drive: checkpoints.zip and arcface_checkpoint.tar
>
> - Copy the arcface_checkpoint.tar into ./arcface_model  
> - Unzip checkpoints.zip, place it in the root dir ./  
>
> [[Google Drive]](https://drive.google.com/drive/folders/1jV6_0FIMPC53FZ2HzZNJZGMe55bbu17R?usp=sharing) [[Baidu Drive]](https://pan.baidu.com/s/1wFV11RVZMHqd-ky4YpLdcA) Password: jd2v

上記で配置したものだけ抜粋すると、こんなフォルダ構成になると思います。

```
SimSwap
├ arcface_model
│ └ arcface_checkpoint.tar
├ checkpoints
│ └ people
│   └ ...
├ insightface_func
│ ├ models
│ │ └ antelope
│ │   ├ glintr100.onnx
│ │   └ scrfd_10g_bnkps.onnx
│ └ ...
└ ...
```

### 5. EncodeError 対応
[SimSwap/usage.md](https://github.com/neuralchen/SimSwap/blob/main/doc/guidance/usage.md) に実行例があるのでそのとおりにすると、以下のエラーが出ました。

```
Traceback (most recent call last):
  File "test_one_image.py", line 35, in <module>
    model = create_model(opt)
  File "F:\Dev\Python\clone\SimSwap\models\models.py", line 18, in create_model
    model.initialize(opt)
  File "F:\Dev\Python\clone\SimSwap\models\fs_model.py", line 64, in initialize
    netArc_checkpoint = torch.load(netArc_checkpoint)
  File "F:\Dev\Python\clone\SimSwap\.venv\lib\site-packages\torch\serialization.py", line 593, in load
    return _legacy_load(opened_file, map_location, pickle_module, **pickle_load_args)
  File "F:\Dev\Python\clone\SimSwap\.venv\lib\site-packages\torch\serialization.py", line 772, in _legacy_load
    result = unpickler.load()
  File "F:\Dev\Python\clone\SimSwap\.venv\lib\site-packages\torch\serialization.py", line 720, in persistent_load
    _check_container_source(*data)
  File "F:\Dev\Python\clone\SimSwap\.venv\lib\site-packages\torch\serialization.py", line 639, in _check_container_source
    f.write(lines)
UnicodeEncodeError: 'cp932' codec can't encode character '\xe0' in position 1153: illegal multibyte sequence
```

Windows 特有の問題かと思いますが、以下のファイルを変更して対応しました。

- .venv\Lib\site-packages\torch\serialization.py

```
635行目
(前) with open(file_name, 'a+') as f:
(後) with open(file_name, 'a+', encoding='utf-8') as f:
```

# 実行例

```
(.venv) > python test_one_image.py --isTrain false  --name people --Arc_path arcface_model/arcface_checkpoint.tar --pic_a_path crop_224/cage.jpg --pic_b_path crop_224/mouth_open.jpg --output_path output/
```

| pic_a | pic_b | result |
|:-:|:-:|:-:|
| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339253/6fac1346-0e68-afa6-ece5-04a9b00eb1dd.jpeg" width="160px"> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339253/3760fc63-008e-7a00-5edd-8afd417420c6.jpeg" width="160px"> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339253/5cd37aad-80d4-061a-6b59-c330c3400d7f.jpeg" width="160px"> |