本記事は、画像処理系の機械学習手法であるTargetCLIPを使用して、2者の顔を自然に合成する方法を解説します。
TargetCLIPとは
TargetCLIPは、ある画像の概念的な「スタイル」を、別の画像の「コンテンツ」組み合わせ新しい画像を生成します。
この画像のブレンディングは、StyleGAN generatorとimage-language matchingであるCLIPを組み合わせて実現されています。
そして、発表された論文によるとこれらが各空間で別々に得られるものよりもはるかに自然なブレンドにつながるとしています。
|
出典: https://github.com/hila-chefer/targetclip |
TargetCLIPの特徴は、従来技術より高レベルな「スタイル」の概念を他方の画像に転送します。
先ほどのジョーカーであれば、従来技術が単に配色やテクスチャを転送していたのに対し、ジョーカーの髪、象徴的な赤い笑顔などをグループ化し転送します。
TargetCLIPの導入手順
セットアップ
それでは早速、開発環境にTargetCLIPをセットアップしていきます。
動作確認は下記の環境で行っています。
OS: Ubuntu 18.04.3 LTS
GPU: GeForce GTX 1080
なお、このデモはPythonで実装しています。
Pythonの実装に不安がある方、Pythonを使った機械学習について詳しく勉強したい方は、以下の書籍やオンライン講座などがおすすめです。
それでは、TargetCLIPをインストールしていきます。他の機械学習環境に影響を与えないためにMinicondaの仮想環境上に構築していきます。Minicondaのインストール手順は公式ドキュメントをご参照ください。
# python version 3.7のconda環境を作成
$ conda create -n targetclip python=3.7
# 作成した環境をアクティベート
$ conda activate targetclip
$ cd targetclip
# gitからコードをclone
$ git clone https://github.com/hila-chefer/TargetCLIP.git
$ cd TargetCLIP
# 関連するライブラリをインストール
$ pip3 install git+https://github.com/openai/CLIP.git
# https://pytorch.org/get-started/previous-versions/ でバージョン確認
$ conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cudatoolkit=10.1 -c pytorch
$ conda install -c conda-forge opencv
$ conda install -c conda-forge matplotlib
# Proxy配下の場合は下記
$ pip3 install "モジュール名" --proxy=http://"username":"password"@proxy:port
# 学習済みモデルをダウンロード(stylegan2-ffhq-config-f.pt)
$ https://drive.google.com/file/d/1EM87UquaoQmk17Q8d5kYIAHqu0dkYqdT/edit
# 実行環境の任意のディレクトリに配置
以上で、セットアップは完了です。
なおGoogle Colaboratoryも提供されているため
とりあえず動かすだけであれば以下の公式のコードもおすすめです
顔の合成(ブレンディング)
ここでは、Google Colaboratoryではなく、ローカル環境で動作可能なコードを記述します。
サンプルは下記のコードです。
下記のコードはTargetCLIP/local_image_transfer.py
として配置されることを前提としています。
import os
# Proxy配下の場合は下記を設定
# os.environ["http_proxy"] = "http://"username":"password"@proxy:port"
# os.environ["https_proxy"] = "http://"username":"password"@proxy:port"
import numpy as np
import torch
import torchvision
from models.stylegan2.model import Generator
import math
import argparse
#@title Aux functions
def get_latent(args, g_ema):
mean_latent = g_ema.mean_latent(4096)
latent_code_init_not_trunc = torch.randn(1, 512).cuda()
with torch.no_grad():
# _, latent_code_init = g_ema([latent_code_init_not_trunc], return_latents=True,
# truncation=args.truncation, truncation_latent=mean_latent)
_, latent_code_init,_ = g_ema([latent_code_init_not_trunc], return_latents=True,
truncation=args.truncation, truncation_latent=mean_latent)
direction = latent_code_init.detach().clone()
direction.requires_grad = True
return direction
def load_model(args):
g_ema = Generator(args.stylegan_size, 512, 8)
g_ema.load_state_dict(torch.load(args.ckpt)["g_ema"], strict=False)
g_ema.eval()
g_ema = g_ema.cuda()
return g_ema
def get_lr(t, initial_lr, rampdown=0.75, rampup=0.005):
lr_ramp = min(1, (1 - t) / rampdown)
lr_ramp = 0.5 - 0.5 * math.cos(lr_ramp * math.pi)
lr_ramp = lr_ramp * min(1, t / rampup)
return initial_lr * lr_ramp
model_args = {
"ckpt": "./learned_models/stylegan2-ffhq-config-f.pt",
"stylegan_size": 1024,
"lr": 0.1,
"truncation": 0.7,
"save_intermediate_image_every": 1,
"results_dir": "results",
"dir_name": "results",
"num_batches": 1,
"real_images": True,
"data_path": "train_faces.pt",
}
dirs = {
'Elsa': 'dirs/elsa.npy',
'Pocahontas': 'dirs/pocahontas.npy',
'Keanu Reeves': 'dirs/keanu.npy',
'Trump': 'dirs/trump.npy',
'Joker': 'dirs/joker.npy',
'Ariel': 'dirs/ariel.npy',
'Doc Brown': 'dirs/doc.npy',
'Beyonce': 'dirs/beyonce.npy',
'Morgan Freeman': 'dirs/morgan.npy',
}
targets = {
'Elsa': 'dirs/targets/elsa.jpg',
'Pocahontas': 'dirs/targets/pocahontas.jpg',
'Keanu Reeves': 'dirs/targets/keanu.jpg',
'Trump': 'dirs/targets/trump.jpg',
'Joker': 'dirs/targets/joker.jpg',
'Ariel': 'dirs/targets/ariel.jpeg',
'Doc Brown': 'dirs/targets/doc_brown.jpg',
'Beyonce': 'dirs/targets/beyonce.jpg',
'Morgan Freeman': 'dirs/targets/morgan_freeman.jpg',
}
sources_ids = {
'Taylor Swift': 67,
'Elon Musk': 4,
'Hillary Clinton': 9,
'Alfie Allen': 34,
'Obama': 61
}
def main() -> None:
parser = argparse.ArgumentParser(description='説明')
parser.add_argument(
'--model_path',
default='./learned_models/stylegan2-ffhq-config-f.pt',
help='modelのパス'
)
parser.add_argument(
'--target',
default='Joker',
help='合成元 Trump,Keanu Reeves, Elsa, Pocahontas, Joker, Ariel, Doc Brown, Beyonce, Morgan Freemanから選択')
parser.add_argument(
'--src',
default='Taylor Swift',
help='合成先 Taylor Swift, Elon Musk, Hillary Clinton, Alfie Allen, Obama'
)
parser.add_argument(
'--alpha',
type=float, default=1.0,
help='min:0, max:2, step:0.1'
)
parser.add_argument(
'--out_dir',
default='./results',
help='出力先'
)
args = parser.parse_args()
model_args['ckpt'] = args.model_path
a=argparse.Namespace(**model_args)
g_ema = load_model(a)
target = args.target
source_name = args.src
sources = torch.from_numpy(np.load('dirs/w_plus.npy'))
source = sources[sources_ids[source_name]].unsqueeze(0)
dir = torch.from_numpy(np.load(dirs[target]))
alpha = args.alpha
dir = dir.cuda()
source = source.cuda()
source_img, _ = g_ema([source], input_is_latent=True, randomize_noise=False)
source_amp, _ = g_ema([source + dir * alpha], input_is_latent=True,
randomize_noise=False)
out_dir = args.out_dir
org_path = os.path.join(out_dir, 'results_orig.png')
mani_path = os.path.join(out_dir, 'results_manipulated.png')
torchvision.utils.save_image(source_img, org_path, normalize=True, range=(-1, 1))
torchvision.utils.save_image(source_amp, mani_path, normalize=True, range=(-1, 1))
if __name__ == "__main__":
main()
上記のプログラムは下記のコマンドで実行できます。
python3 local_image_transfer.py \
--model_path ./learned_models/stylegan2-ffhq-config-f.pt \
--target Joker \
--src Obama \
--alpha 1.1 \
--out_dir ./results
実行結果は以下の通りです。
口角の上がり方や、目元の変化などが非常に自然に変換されていることが見て取れます。
TargetCLIPはこのように自然な変換が可能となるため法律や倫理に反さない利用が求められます。
まとめ
本記事では、TargetCLIPで2者の顔を合成する方法をご紹介しました。
パッと見では、本当に本人がその恰好をしたのか、合成によって生成された画像なのか判断が難しい画像も存在します。
このため、当たり前のことですが、誰かの名誉を毀損するような悪用は厳禁となります
また本記事では、機械学習を動かすことにフォーカスしてご紹介しました。
もう少し学術的に体系立てて学びたいという方には以下の書籍などがお勧めです。ぜひご一読下さい。
リンク
リンク
また動かせるだけから理解して応用できるエンジニアの足掛かりに下記のUdemyなどもお勧めです。
参考文献
1. IMAGE-BASED CLIP-GUIDED ESSENCE TRANSFER
2. hila-chefer/TargetCLIP
3. Casual GAN Paper - 66: TargetCLIP
0 件のコメント :
コメントを投稿