StyleGAN2の潜在空間に、新垣結衣は住んでいるのか？

#1.はじめに
　前回、[**「ProgressiveGAN の潜在空間に、新垣結衣は住んでいるのか？」**](https://qiita.com/jun40vn/items/a4f71c42b5ff52bc98de)というテーマについて 調べてみた結果、残念ながら住んでいないことが分かりました。

　今回は、最新の [**StyleGAN2**](https://github.com/NVlabs/stylegan2) を使って同じテーマに取り組んでみたいと思います。なお、コードは Google Colab で作成し Github に上げてありますので、自分でやってみたい方は、この[**「リンク」**](https://github.com/cedro3/StyleGAN2/blob/master/Search_for_Yui.ipynb)をクリックし表示されたシートの先頭にある**「Colab on Web」**ボタンをクリックすると動かせます。

#2.StyleGAN2とは？
　まず、[**StyleGAN**](https://github.com/NVlabs/stylegan)について説明します。
![stylegan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/bda29b16-1158-703d-abb8-2a769378fbf8.png)

　これは、(a)今までのGAN（ProgressiveGAN） と(b) StyleGANのネットワーク構造を比較した図です。StyleGANは今までとは構造をがらりと変えて、**Mapping network** と**Synthesis network** の２つで構成されています。

　**Mapping network** は8層の全結合層から成り、入力の**潜在変数z** (1,512)を中間出力である**潜在変数w** (18,512)にマッピングします。

　**Synthesis network**は9層から成り、入力は**4×4×512の定数**で、そこへ**潜在変数w**(A)と**ノイズ**(B)が各層に入力されます。潜在変数wは各層の入力が2つのため、9層×2=18個あります。

　潜在変数wは**スタイル**と呼ばれ**主な画像生成**（顔の形、肌の色、髪の毛の色、性別など）をコントロールし、**ノイズ**は**細部の特徴**（髪質や髪の流れ、ヒゲ、そばかす、肌質など）をコントロールします。Synthesis networkの解像度は4×4から順次アップサンプリングし、最終的には1024×1024になります。

　このStyleGANは2018年にNVIDIAから発表されました。そして、StyleGAN2は**StyleGANの改良版**(AdaINの代わりにCNNのWeightを正規化など)として2019年にNVIDIAから発表されたました。

#3.新垣結衣の潜在変数をどう見つけるか
![スクリーンショット 2020-07-01 10.08.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/ca108783-7798-d948-6b99-71e251fe7f47.png)

　潜在変数z(1×512)より、潜在変数w(18×512)の方が明らかに表現力が豊なので、潜在変数wの探索を行います。

　アルゴリズムは、Synthesis networkの9個ある各層において、潜在変数wを適当に初期化して **inital image** を出力し、**target image** (新垣結衣の画像)との差をロスとして、ロスが出来るだけ小さくなるように潜在変数wを最適化するものです。

　そのために、**target image** は9種類の解像度の画像(4×4〜1024×1024)で用意しておく必要があります。また、顔画像の切り取り位置が適切でないと今まで学習した内容が生かしきれず、上手く画像生成が出来ないことに注意が必要です。

　それでは、実際にやってみましょう。

#4.手順
**1)顔画像の切り取り**
　普通は**OpenCV**でやるわけですが、StyleGAN2が学習した[**FFHQデータセット**](https://github.com/NVlabs/ffhq-dataset)は、**dlib**を使い**align**(顔が直立するように回転させる)して**独自の設定の範囲**を切り取って作成されているので、自分でオリジナル画像を使う場合も同様な処理を行います。
![スクリーンショット 2020-07-01 17.43.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/72b04a6f-108e-925b-5808-811e7507cd71.png)
　そして、切り出した顔画像(target image)は、1024×1024の大きさにリサイズします。


**2)マルチ解像度データの作成**
　切り取った顔画像を9種類の解像度の画像に変換します。`dataset_tool.py`を使って、Tensorflowの仕様であるマルチ解像度の画像TFRecordを作成します。

**3)潜在変数wの探索**
　マルチ解像度の画像を元に、各層でロスを最小化して、潜在変数wを探索します。結果をターゲット画像は「target」、探索した潜在変数wを元に生成した画像は「generate」としてまとめてみると、こんな感じ。

![スクリーンショット 2020-07-01 13.47.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/9428904d-c6cf-dcb7-63b1-a48a996df918.png)

　割と出来が良かったものを選んでいますが、まずまずの出来ではないでしょうか。後一味足らないのが残念で７０点くらいかな。

**4)潜在変数wによるアニメーション**
　２つ画像の潜在変数wの差を等分して少しづつ変化させて画像を生成すると、いわゆるアニメーションが作成できます。

![movie_256.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209705/a7c751ac-3b99-0007-2307-dca015401625.gif)

　オリジナルは1024×1024サイズですが、それではQiitaにアップロード出来ないので、その1/16である256×256サイズで表示しています。さすがに高品質です。

※ このブログで表示している画像は探索試行回数1000回のものですが、Google Colab での探索試行回数は300に設定してあります。探索試行回数を変更したい場合は、**projector.py** の **num_steps** の値を変更して下さい。

#5.結論
　結論は、**「StyleGAN2の潜在空間には、かなり新垣結衣似の人が住んでいました」**(笑)です。

（参考）
[StyleGANを遊び尽くせ!! ~追加学習不要の画像編集~](https://qiita.com/pacifinapacific/items/1d6cca0ff4060e12d336)