今回はStylegan2-adaというものを使って顔画像を変化させるようなアニメーションを作っていきたいと思います。
- 静止画2枚をStylegan2-adaで動かす
[StyleGAN2-ADA] 機械学習で顔画像のモーフィング動画を作成 [Python]を参考にしてやっていきますよ。
作成するアニメーション
作成するのは静止画2枚を使ってそれをこんな感じでアニメーションさせたものです。
プログラムを使う必要があるけど、GoogleColaboratoryから誰でも使うことができます。
Stylegan2-adaはStlyeGAN2にADAっていう技術を取り込んだものがStylegan2-adaみたいです。ただ正直Githubのページ見てもよく分からないですね。
人工知能関連のプログラムに詳しい人なら見て分かるんでしょうが、凡人には無理です。
GoogleColaboratoryからコードを実行する
GoogleColaboratoryから実行していきます。ランタイムはGPUにして進めましょう。
!nvidia-smi
%cd /content
!git clone https://github.com/NVlabs/stylegan2-ada-pytorch.git
# for align face
!git clone https://github.com/adamian98/pulse.git
顔の位置を画像から検出するためにpulseも入れておきます。ライブラリのインストールとインポートを行います。
!pip install moviepy
# ninja
!wget https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip > /dev/null
!sudo unzip ninja-linux.zip -d /usr/local/bin/ > /dev/null
!sudo update-alternatives --install /usr/bin/ninja ninja /usr/local/bin/ninja 1 --force > /dev/null
!pip install imageio==2.4.1
%cd /content/stylegan2-ada-pytorch
import cv2
import numpy as np
from PIL import Image
import dlib
from matplotlib import pyplot as plt
import torch
import dnnlib
import legacy
import imageio
from tqdm.notebook import tqdm
from moviepy.video.fx.resize import resize
from moviepy.editor import VideoFileClip
画像を入れるためのディレクトリを作成します。
%cd /content/stylegan2-ada-pytorch
!rm -rf inputs
!mkdir -p inputs/img inputs/align
imgっていうフォルダができるので、そこに画像を2枚入れておきます。(ドラッグ&ドロップで可能)
画像から顔の部分を切り抜くためにpulseのalign_face.pyを使います。
NETWORK = "https://nvlabs-fi-cdn.nvidia.com/stylegan2-ada-pytorch/pretrained/ffhq.pkl"
SOURCE_NAME = '/content/stylegan2-ada-pytorch/src.jpg'
TARGET_NAME = '/content/stylegan2-ada-pytorch/dst.jpg'
%cd /content/pulse
!python align_face.py \
-input_dir /content/stylegan2-ada-pytorch/inputs/img \
-output_dir /content/stylegan2-ada-pytorch/inputs/align \
-output_size 1024 \
-seed 12
これでinputsのalignフォルダに顔画像が切り抜かれた画像が配置されました。
projector.pyを使って画像を投影します。指定するのはさっき切り取った顔の画像です。
%cd /content/stylegan2-ada-pytorch
!python projector.py \
--save-video 0 \
--num-steps 1000 \
--outdir=outputs/src \
--target=inputs/align/src_0.png \
--network={NETWORK}
%cd /content/stylegan2-ada-pytorch
!python projector.py \
--save-video 0 \
--num-steps 1000 \
--outdir=outputs/dst \
--target=inputs/align/dst_0.png \
--network={NETWORK}
ただ何やっているのかよくわかりません。projector.pyのコード見てもAI関連のプログラミング知識ないから本当に分かりません。
最後に動画を作成します。
STEPS = 100
FPS = 20
FREEZE_STEPS = 20
%cd /content/stylegan2-ada-pytorch
lvec1 = np.load('./outputs/src/projected_w.npz')['w']
lvec2 = np.load('./outputs/dst/projected_w.npz')['w']
network_pkl = "https://nvlabs-fi-cdn.nvidia.com/stylegan2-ada-pytorch/pretrained/ffhq.pkl"
device = torch.device('cuda')
with dnnlib.util.open_url(network_pkl) as fp:
G = legacy.load_network_pkl(fp)['G_ema'].requires_grad_(False).to(device) # type: ignore
diff = lvec2 - lvec1
step = diff / STEPS
current = lvec1.copy()
target_uint8 = np.array([1024,1024,3], dtype=np.uint8)
video = imageio.get_writer('./movie.mp4', mode='I', fps=FPS, codec='libx264', bitrate='16M')
for j in tqdm(range(STEPS)):
z = torch.from_numpy(current).to(device)
synth_image = G.synthesis(z, noise_mode='const')
synth_image = (synth_image + 1) * (255/2)
synth_image = synth_image.permute(0, 2, 3, 1).clamp(0, 255).to(torch.uint8)[0].cpu().numpy()
repeat = FREEZE_STEPS if j==0 or j==(STEPS-1) else 1
for i in range(repeat):
video.append_data(synth_image)
current = current + step
video.close()
clip = VideoFileClip('./movie.mp4')
clip = resize(clip, height=420)
clip.ipython_display()
これで指定した2枚の画像をモーフィングする動画ができました。
まとめ
こういうのすごいですよね、画像が2枚あればそれっぽい変化するアニメーションを作れてしまいます。人工知能に詳しい人なら具体的に何をやっているのかっていうことが分かると思うけど、凡人の自分には無理でした。
(Web開発関連のプログラミング知識と全然違うから苦しいんだよなあ)
とはいえAIの力は凄いな。