MagicAnimateをUbuntuで動かす

# この記事を読むと何がわかる？
Magic Animateを使って、自分で用意した人物の静止画を、自分で用意した動画の動きで動かす方法が分かります。

**用意するもの**
・人物が写った画像1枚
・人物の動きを表現する動画1つ

**出来上がるもの**
・画像の人物が、動画の動きをする動画

# 時間のない方へ
いろいろやったらこんな感じでできました。
![gird.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3746743/56e89ce8-26ca-2845-b5f8-ba9f3b5620bc.gif)
左の静止画と真ん中の動画を入れると、一番右の動画が出力されました。
これ以降の文章は、なるべく手短にこれをお手元のPCでこれを再現する手順をご説明いたします！

# そもそもMagic Animateって何？

拡散モデルベースの人物画像のアニメ化のフレームワークです。
　・時間的一貫性の向上
　・参照画像の忠実な保持
　・アニメーションの忠実度の向上
が特徴です。CVPR2024でこの技術の論文が採択されています。

https://showlab.github.io/magicanimate/


# 用意した環境
|環境|     | 
| --- | --- | 
|OS|Ubuntu 22.04.4 LTS| 
|GPU|RTX 3060| 
|GPUメモリ|12GB| 
|anaconda|24.3.0| 

インストールされている前提のもの
|環境|インストール方法| 
| --- | --- | 
|git lfs|https://github.com/git-lfs/git-lfs/wiki/Installation| 
|anaconda|https://www.anaconda.com/download| 
|ffmpeg|sudo apt install ffmpeg| 
|imagemagick|sudo apt install imagemagick| 
|aria2c|sudo apt install aria2| 


# まずはサンプルを動かしてみる
１．コード一式を取ってきて、magic-animateディレクトリに移動する。
```bash
git clone https://github.com/magic-research/magic-animate
```

２．モデルをダウンロードする。
```bash
cd magic-animate
mkdir pretrained_models/stable-diffusion-v1-5
cd pretrained_models/stable-diffusion-v1-5
aria2c -x5 --dir=. -o scheduler/scheduler_config.json https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/scheduler/scheduler_config.json
aria2c -x5 --dir=. -o v1-5-pruned-emaonly.safetensors https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/v1-5-pruned-emaonly.safetensors
aria2c -x5 --dir=. -o text_encoder/config.json https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/text_encoder/config.json
aria2c -x5 --dir=. -o text_encoder/pytorch_model.bin https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/text_encoder/pytorch_model.bin
aria2c -x5 --dir=. -o tokenizer/tokenizer_config.json https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/tokenizer/tokenizer_config.json
aria2c -x5 --dir=. -o tokenizer/merges.txt https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/tokenizer/merges.txt
aria2c -x5 --dir=. -o tokenizer/special_tokens_map.json https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/tokenizer/special_tokens_map.json
aria2c -x5 --dir=. -o tokenizer/vocab.json https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/tokenizer/vocab.json
aria2c -x5 --dir=. -o unet/config.json https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/unet/config.json
aria2c -x5 --dir=. -o unet/diffusion_pytorch_model.bin https://huggingface.co/runwayml/stable-diffusion-v1-5/resolve/main/unet/diffusion_pytorch_model.bin
cd ..
git clone https://huggingface.co/stabilityai/sd-vae-ft-mse ./pretrained_models/sd-vae-ft-mse/
git lfs clone https://huggingface.co/zcxu-eric/MagicAnimate ./pretrained_models/MagicAnimate/
```

３．仮想環境を作る
```bash
cd magic-animate
conda env create -f environment.yaml
conda activate manimate
```

４．とりあえずサンプルを動かす
```bash
cd magic-animate
bash scripts/animate.sh
```

５．結果を眺める。
以下の場所にmp4ファイルができているはずです。
(xxのところは実行日時が入ります。)
```bash
magic-animate/samples/animation2-20xx-xx-xxTxx-xx-xx/videos/monalisa_running.mp4
magic-animate/samples/animation2-20xx-xx-xxTxx-xx-xx/videos/monalisa_running/grid.mp4
```


![output1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3746743/aa43329d-f8d9-f0f8-44f3-74a9f1fca93d.gif)
おー、できてるできてる。



**注意**：GUIモードで動かすと、12GBメモリがあっても足りない。

# 自分の用意した画像と動画を使う
ここからが本題です。
自分で画像と動画を用意して、好きなものを作りたいですよね。

# 動画を変換するツールを用意する

そのためにまず、動画を変換するプログラムを用意します。
１． vid2denseposeのコード一式を取得する。
```bash
git clone https://github.com/Flode-Labs/vid2densepose
```

２． anacondaの仮想環境を作る。
```bash
# python3.9環境
conda create --name vid2densepose python=3.9
conda activate vid2densepose

# pytorchとかcuda toolkitをインストールする
conda install pytorch==1.10.1 torchvision==0.11.2 torchaudio==0.10.1 cudatoolkit=11.3 -c pytorch -c conda-forge

# detectron2をインストールする
python -m pip install detectron2==0.6 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu113/torch1.10/index.html

# 関係するモジュールをインストールする
pip install opencv-python av scipy

# denseposeを含むコードをダウンロードする
git clone https://github.com/facebookresearch/detectron2/
ln -s detectron2/projects/DensePose/densepose densepose
```


# 動画を取ってくる
動きを表現する動画を作るために、Pexelsで配布している無料動画を使ってみます。

https://www.pexels.com/ja-jp/video/2873755/

こちらの動画をvid2denseposeで、MagicAnimateで使用できる動画に変換してみます。
まず、4k動画を512x512に変換します。
ffmpegを使って変換します。

```bash
ffmpeg -i 2873755-uhd_3840_2160_25fps.mp4 -vf "scale=-1:512,crop=w=512:h=512:x=300:y=0" -b 2M -ss 11 -t 5 dance.mp4
```
引数の意味は以下です。
**注意**：GPUメモリが12GBだと、5秒を超える動画の変換時にGPUメモリ不足になることがあるようです。

|オプション|引数|意味| 
| --- | --- | ---| 
| -i | 2873755-uhd_3840_2160_25fps.mp4 | 変換したい元動画のファイル名| 
|-vf|"scale=-1:512,crop=w=512:h=512:x=300:y=0"|高さを512にリサイズして、(300,0)-(300+512,0+512)でクリップします。| 
|-b|2M|出力動画のビットレートは、2Mbpsとする。|
|-ss|11|11秒目を始点として切り出す。|
|-t|5|始点から5秒間の動画とする。| 


作成されたdance.mp4をvid2denseposeで動画にします。

```bash
conda activate vid2densepose
cd vid2densepose
python main.py -i dance.mp4 -o dense.mp4
```

ちゃんと変換されたのが出てきた！
![dense.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3746743/91da3252-88fd-5a34-273a-01fb9775c5b8.gif)

**これで、動作用の動画の準備は完了です！**

# 人物の写真画像を用意する
動かしたい人物写真として、こちらの画像を選んでみました。

https://www.photo-ac.com/main/detail/24497610

Imagemagicを使ってアスペクト比を保ったまま512x512にします。
```bash
convert 24497610_l.jpg -resize 512x512^ -gravity center -extent 512x512 input.png
```
|オプション|引数|意味| 
| --- | --- | ---| 
| -resize | 512x512^ | アスペクト比を保ったまま縦か横の小さい方が512になるようにリサイズする| 
|-gravity|center|切り取るときに画像の中心を切り取ることにする| 
|-extent|512x512|512x512で切り取る| 

**これで、人物の写真画像の準備は完了です！**


# yamlファイルの修正
まずオリジナルをコピーします。
```bash
cp configs/prompts/animation.yaml animation2.yaml
```

以下のように感じで修正します。
ファイル名は、ファイルがあるパスを書いてください。
|名前|値|意味| 
| --- | --- | ---| 
| source_image | input.png | 人物が写った画像のファイル名| 
|video_path|dense.mp4|人物の動きを表現する動画のファイル名| 
```yaml
pretrained_model_path: "pretrained_models/stable-diffusion-v1-5"
pretrained_vae_path: "pretrained_models/sd-vae-ft-mse"
pretrained_controlnet_path: "pretrained_models/MagicAnimate/densepose_controlnet"
pretrained_appearance_encoder_path: "pretrained_models/MagicAnimate/appearance_encoder"
pretrained_unet_path: ""

motion_module: "pretrained_models/MagicAnimate/temporal_attention/temporal_attention.ckpt"

savename: null

fusion_blocks: "midup"

seed:           [1]
steps:          25
guidance_scale: 7.5

source_image:
  - "input.png" # ここを作成した人物写真のファイル名にします！
video_path:
  - "dense.mp4" # ここを作成した動画のファイル名にします！

inference_config: "configs/inference/inference.yaml"
size: 512
L:    16
S:    1 
I:    0
clip: 0
offset: 0
max_length: null
video_type: "condition"
invert_video: false
save_individual_videos: false
```

**最後に変換するための処理を呼び出して、祈ります！**
```bash
conda activate manimate
cd magic-animate
python3 -m magicanimate.pipelines.animation --config animation2.yaml
```



# 動画の完成
以下の位置にファイルが保存されます！
(xxのところは実行日時が入ります。)
```
magic-animate/samples/animation2-20xx-xx-xxTxx-xx-xx/videos/input_dense.mp4
magic-animate/samples/animation2-20xx-xx-xxTxx-xx-xx/videos/input_dense/grid.mp4
```
![input_dense.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3746743/cbf103bf-1b33-c51f-0819-f619aff7f37a.gif)

**良い点**
・後ろで縛っている髪が顔の向きに関わらず再現されている
・ある程度近づいたときの顔の崩れが許容できるレベル

**悪い点**
・顔が遠すぎると表現が雑
・スカートとズボンで迷っていて一貫誠意が壊れている
・背中を向いているときをうまく表現てきていない

**気づいた点**
・動画の人物の体格に近くなるので、静止画と動画の性別や体格は合わせといた方が再現度が高そう。

**しかたない点**
・表情は再現されない。だって入力に目鼻口の位置情報ないから。

# おわりに
いろんな可能性を感じさせてくれる面白い技術でした。
もっと他の静止画や動画を試してみたいのですが、一回一回、結構時間かかります。
もっと速くてメモリの大きいGPUが格安で発売される日を夢見て待つことにします。