[iPERCore] 機械学習で写真を踊らせてみる [Python]

2022年2月19日土曜日

Artificial Intelligence

本記事では、Liquid Warping GAN with Attention: A Unified Framework for Human Image Synthesisと呼ばれる機械学習手法を使って、写真に写る人を踊らせる方法をご紹介します。

アイキャッチ

Liquid Warping GAN with Attentionとは

概要

Liquid Warping GAN with Attentionは、2020年11月に論文発表された人間の動きの模倣、外観の転送、新しいビューの合成など、人間の画像を合成する機械学習手法です。そしてiPERCoreはその再現実装です。

言葉で説明するよりも見ていただくと一目瞭然ですのでまずはこちらをご覧ください。

サンプル

上記は論文発表元が提供しているサンプルデータから生成した出力結果です。
左のトランプさんの画像と、中央のおじ様の動画を入力すると、右のおじ様の動きを模倣したトランプさんの動画が出力されます。

このように本手法では、入力画像の外観(上記ではトランプさん)を転送し、入力動画の動き(上記ではおじ様)を模倣した新しいビューを生成します。

従来手法との差異

従来手法では、主に2Dキーポイントを使用して姿勢推定を行います。しかし、これは、人体構造の位置情報を表現するだけであり、顔の形状や衣類の詳細などパーソナライズした形状を特徴つけたり、手足の回転などを表現することができませんでした。

本手法では、3D body mesh recovery moduleを使用して、関節の位置や回転をモデル化するだけでなく、パーソナライズされた体型をなどを特徴づけることを実現しています。
これらの情報を保持するため、画像空間と特徴空間の両方のソース情報を伝播するため、Attentional Liquid Warping Block (AttLWB)を備えたAttentional Liquid Warping GANを提案しています。

出典: Liquid Warping GAN with Attention: A Unified Framework for Human Image Synthesis

手法の詳細は論文をご確認ください。

デモ(Colaboratory)

それでは、実際に動かしながらiPERCoreの動画生成を行っていきます。
ソースコードは本記事にも記載していますが、下記のGitHubでも取得可能です。
GitHub - Colaboratory demo

また、下記から直接Google Colaboratoryで開くこともできます。
Open In Colab

なお、このデモはPythonで実装しています。
Pythonの実装に不安がある方、Pythonを使った機械学習について詳しく勉強したい方は、以下の書籍やオンライン講座などがおすすめです。

環境セットアップ

それではセットアップしていきます。 Colaboratoryを開いたら下記を設定しGPUを使用するようにしてください。

「ランタイムのタイプを変更」→「ハードウェアアクセラレータ」をGPUに変更

はじめにライブラリをインストールします。

!pip install moviepy==0.2.3.5 imageio==2.4.1
!pip install yt-dlp

次にライブラリをインポートします。

import os
import os.path as osp
import platform
import argparse
import time
import sys
import subprocess

from google.colab import files
from moviepy.editor import *
from moviepy.video.fx.resize import resize

環境変数を設定します。

!ls /usr/local/ | grep cuda

# CUDA_HOMEにcuda-11のパスを設定
os.environ["CUDA_HOME"] = "/usr/local/cuda-11"

!echo $CUDA_HOME

以上で環境セットアップ完了です。

iPERCoreのセットアップ

GitHubからソースコードを取得します。

!git clone https://github.com/iPERDance/iPERCore.git

# Commits on Oct 31, 2022
%cd /content/iPERCore
!git checkout 61f7e086316d7f64779be75d3a771da4e1e4d441

ライブラリをインストールします。

%cd /content/iPERCore/

# cuda11.2以上の場合cuda11.1の設定でセットアップ
!sed -i '158i \    version = version if version != 11.2 else 11.1' setup.py

!python setup.py develop

最後に学習済みモデルとサンプルデータをダウンロードします。

%cd /content/iPERCore

# download samples
!wget -O assets/samples.zip  "http://101.32.75.151:10086/samples.zip"
!unzip -o assets/samples.zip -d  assets
!rm assets/samples.zip

# download checkpoints
!wget -O assets/checkpoints.zip "http://101.32.75.151:10086/checkpoints.zip"
!unzip -o assets/checkpoints.zip -d assets/

!rm assets/checkpoints.zip

Motion Imitation

それでは、動画の動きを模倣させて写真を躍らせてみましょう。

入力する画像は下記3パターンから選択可能です。
入力する画像が多いほど入力情報が多いため精細な結果が出力されやすくなります。

また、入力画像は全身がはっきりと写っている画像であることが望ましいです。コントラストが極端な写真などはうまく出力されない場合があります。

  1. 正面画像(front_only)
  2. 正面画像+背面画像(front_back)
  3. 正面画像+背面画像+背景画像(front_back_bg)

セルを実行する前に下図を設定することで入力画像のパターンを切り替えることができます。

パターン選択
%cd /content/iPERCore
!rm -rf images
!mkdir images


#@markdown  front_only:正面画像のみ、front_back:正面、背面画像、fron_back_bg:正面、背面、背景画像
model_type = "front_back"  #@param ["front_only", "front_back", "front_back_bg"] {allow-input: false}

gpu_ids = "0"
#@markdown 出力画像サイズ
image_size = 512 #@param {type:"integer"}
num_source = 2
assets_dir = "/content/iPERCore/assets"
output_dir = "/content/iPERCore/results"
cfg_path = "/content/iPERCore/assets/configs/deploy.toml"

# model設定
model_id = "donald_trump_2"
if model_type == "front_back":
  model_id = "axing_1"
elif model_type == "front_back_bg":
  model_id = "afan_6=ns=2"

%cd /content/iPERCore/images
# src画像アップロード
if model_type == "front_only":
  print("正面画像をアップロードしてください")
  front_img = files.upload()
  front_img = list(front_img.keys())

  front_img_full_path = os.path.join("/content/iPERCore/images", front_img[0])
  src_path = "\"path?=" + front_img_full_path + ",name?=front_only\""
elif model_type == "front_back":
  print("正面画像をアップロードしてください")
  front_img = files.upload()
  front_img = list(front_img.keys())
  print("背面画像をアップロードしてください")
  back_img = files.upload()
  back_img = list(back_img.keys())

  src_path = "\"path?=/content/iPERCore/images,name?=front_back\""
elif model_type == "front_back_bg":
  print("正面画像をアップロードしてください")
  front_img = files.upload()
  front_img = list(front_img.keys())
  print("背面画像をアップロードしてください")
  back_img = files.upload()
  back_img = list(back_img.keys())
  print("背景画像をアップロードしてください")
  bg_img = files.upload()
  bg_img = list(bg_img.keys())

  bg_img_full_path = os.path.join("/content/iPERCore/images", bg_img[0])
  src_path = "\"path?=/content/iPERCore/images," \
             "name?=front_back_bg," \
             "bg_path?=" + bg_img_full_path + "\""

上記で入力画像がセットアップされます。

次に動画をアップロードします。アップロードする際には、動きを模倣する動画の範囲を切り出すことができます。
下図の例では、アップロードした動画の47~60秒の箇所を切り出して使用します。

動画切り出し
!mkdir videos
!rm -rf vidoos
%cd /content/iPERCore/videos
#@markdown 動画の切り抜き(秒)  end=0は変更なし
start =  47#@param {type:"integer"}
end =  60#@param {type:"integer"}

print("動きを参照する動画をアップロードしてください")
video = files.upload()
video = list(video.keys())

clip = VideoFileClip(video[0])
if end != 0:
    if start < end and end <= clip.duration:
      clip = clip.subclip(start, end)

subclip_path = os.path.join("/content/iPERCore/videos", "sub_"+video[0])
clip.write_videofile(subclip_path)
video_name = os.path.splitext(os.path.basename(video[0]))[0]

ref_path = "\"path?=" + subclip_path + "," \
             "name?=" + video_name + "," \
             "pose_fc?=400\""

セットアップした画像と動画を使用してMotion Imitationを実行します。

%%time

%cd /content/iPERCore/

!python -m iPERCore.services.run_imitator  \
  --gpu_ids     $gpu_ids       \
  --num_source  $num_source    \
  --image_size  $image_size    \
  --output_dir  $output_dir    \
  --model_id    $model_id      \
  --cfg_path    $cfg_path      \
  --src_path    $src_path      \
  --ref_path    $ref_path

最後に生成した動画をMoviePyで表示します。

%cd /content/iPERCore/
results_video = "/content/iPERCore/results/primitives/" + model_type + "/synthesis/imitations/" + model_type + "-" + video_name + ".mp4"

clip = VideoFileClip(results_video)
clip = resize(clip, height=420)
clip.ipython_display()

出力結果は以下の通りです。 なお画像はぱくたそ様の画像を、動画は論文発表元のサンプルデータを使用しています。

正面画像のみ

背面画像を追加した出力結果は以下の通りです。

正面、背面画像結果

背面画像を追加したほうが、顔の周りの形状などがやや精細に出力されています。

最後に、星野源さんの恋の振付動画を使用して、さきほどの画像を動かしてみた結果は以下の通りです。

恋振付

まとめ

本記事では、Liquid Warping GAN with Attentionを用いて写真を踊らせる方法をご紹介しました。
写真と動画さえあれば様々な入力に適応するためご自身の写真などを使ってみると面白いかもしれません。
これを機に機械学習に興味を持つ方が一人でもいらっしゃいましたら幸いです。

また本記事では、機械学習を動かすことにフォーカスしてご紹介しました。
もう少し学術的に体系立てて学びたいという方には以下の書籍などがお勧めです。ぜひご一読下さい。


また動かせるだけから理解して応用できるエンジニアの足掛かりに下記のUdemyなどもお勧めです。

参考文献

1.  論文 - Liquid Warping GAN with Attention: A Unified Framework for Human Image Synthesis

2. GitHub - iPERDance/iPERCore

AIで副業ならココから!

まずは無料会員登録

プロフィール

メーカーで研究開発を行う現役エンジニア
組み込み機器開発や機会学習モデル開発に従事しています

本ブログでは最新AI技術を中心にソースコード付きでご紹介します


Twitter

カテゴリ

このブログを検索

ブログ アーカイブ

TeDokology