【Houdini】PDGでAI美少女を動かす

こちらの記事は Houdini Advent Calendar 2023 21日目の記事です。


## はじめに
Advent Calendar初参加です、よろしくお願いいたします。

皆さんは[Stable Diffusion](https://ja.stability.ai/stable-diffusion)のような画像生成AIを使用したことがあるでしょうか？ 画像生成AIは主にWebUIで操作するのが主流になっていると思いますが、いろんな設定パターンで大量に画像を生成したり、複数の生成工程を組もうとするとプログラムによって管理したくなります。

本記事はPDGでStable Diffusion（Diffusers）を使用する方法について紹介します。それと最後に、最近流行りの[MagicAnimate](https://showlab.github.io/magicanimate/)を使用して生成した画像を動かすところまでやってみます。


最終的にこんな感じになります。
![ezgif.com-video-to-gif-converted (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/ff8ae189-aa7e-593d-c346-8a02137553a4.gif)


## 仮想環境の構築
はじめに仮想環境を構築して、AI画像生成ライブラリのdiffusersをインストールする必要があります。

Houdini 20.0から[Python Virtual Environment TOP](https://www.sidefx.com/docs/houdini/nodes/top/pythonvenv.html)が追加されていたので、使用してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/e1ebaa38-c689-1615-34fd-c03d6f206596.png)

requirements.txtで必要なライブラリを指定します。
```requirements.txt
--extra-index-url https://download.pytorch.org/whl/cu118
accelerate==0.22.0
diffusers==0.21.4
huggingface-hub==0.16.4
omegaconf==2.3.0
transformers==4.32.0
torch==2.0.1
```

ノードをクックすることで、仮想環境が構築され必要なパッケージがインストールされるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/d674a564-6b05-af54-7c2d-e5b1f60a7918.png)

## TOPs上で画像生成する
ここからは実際にdiffusersライブラリを使用して画像生成を行います。
Python Script TOPでdiffusersライブラリを動かしてみます。
`Python Bin`をVirtual Environmentにすることで先ほどの仮想環境下でpythonを実行してくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/a1db2c45-1946-9fe3-0307-eb0c9e21122d.png)

Codeはdiffusersのサンプルコードをもとに実装しています。
``` python:
from diffusers import DiffusionPipeline
import torch

from pdgcmd import localizePath


pipeline = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16)
pipeline.to("cuda")
image = pipeline("An image of a squirrel in Picasso style").images[0]

savepath = localizePath('__PDG_DIR__/squirrel.png')

image.save(savepath)

work_item.addOutputFile(savepath, "file/image")
```

ノードをクックすると画像が生成されます。ワークアイテムのOutputから画像を確認できます。ここではpython上で指定した`ピカソ風のリスの画像`が出力されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/d2a201d1-a50c-4fbd-a7ce-a602c2fb9355.png)


## Civitaiのカスタムモデルを使用する

ひとまず、PDG上で画像生成を行うことができました。最後に行うMagicAnimateでは人の画像からアニメーションを生成するため、ここからはカスタムモデルを使用して元となる女の子の画像を生成していきたいと思います。

[Civitai](https://civitai.com/)はstable diffusionのモデルを共有するサイトです。カスタムモデルを使用することでよりハイクオリティな画像を生成できます。
ただし、後述しますがdiffusersから使用するには少し工夫が必要になります。

まずはCivitaiからモデルファイルをダウンロードします。本記事では[majicmix-realistic](https://civitai.com/models/43331/majicmix-realistic)というモデルを使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/41ce892f-1fe3-b6e9-4df3-1c0c3435f0a3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/cd937943-4895-ac83-9c54-74b550ae0e2a.png)

TOPsからはFile Pattern TOPで取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/bf54c82c-21bf-71a7-53c9-0587715b3763.png)

ダウンロードしたモデルファイルはこのままでは使用できません。
.safetensorsファイルで配布されるため、diffusersパッケージから使用できるように変換する必要があります。
[変換用のスクリプト](https://raw.githubusercontent.com/huggingface/diffusers/v0.21.4/scripts/convert_original_stable_diffusion_to_diffusers.py)はdiffusersのGithubレポジトリで提供されているため、参考にしてPython Script TOPを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/467b6963-da92-1f2c-0a20-ee03a9f45a87.png)

ノードをクックすると`Models/majicmixRealistic_v7/`フォルダー以下に変換後のモデルファイルが保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/8e5d7fc1-dba1-109c-e4d6-7153f9eed214.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/6cb8e655-dcbc-2931-37c7-801daa2174de.png)

Houdini上で変換したカスタムモデルを読み込んで画像生成を行います。
一枚の画像生成を行う場合は先ほどと同じPython Script TOPで十分ですが、せっかくPDGを使用しているのでseed値違いで複数の画像を生成したいです。
Python Processer TOPを使用して`Batch Size`パラメーターで指定した数だけワークアイテムを生成して画像生成を行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/9c553ebc-97f5-2256-fc87-6a610db092d4.png)

:::note info

Python Processer TOPではPython Script TOPのようにノードのインターフェースから仮想環境を指定できません。
Generate Callback中で`work_item.setCommand()`を仮想環境のPythonからワークスクリプトを実行するように指定します。
```python:
# Evaluate the parameter ports in the context
prompt = self["prompt"].evaluateString()
negativeprompt = self["negativeprompt"].evaluateString()
width = self["width"].evaluateInt()  
height = self["height"].evaluateInt()  
batches = self["batches"].evaluateInt() 

for upstream_item in upstream_items:
    venvroot = upstream_item.fileAttribValue("venvroot").path
    venvpython = f"{venvroot}/Scripts/python"

    for idx in range(batches):
        new_item = item_holder.addWorkItem(index=idx, parent=upstream_item)
        
        new_item.setStringAttrib("prompt", prompt)
        new_item.setStringAttrib("negativeprompt", negativeprompt)
        new_item.setIntAttrib("width", width)
        new_item.setIntAttrib("height", height)
        
        new_item.setCommand(f"{venvpython} __PDG_SCRIPTDIR__/text_to_image.py")
```
:::

ノードをクックすることで複数の画像が生成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/c63d885d-55a1-9ff9-878e-4d11540c6568.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/7971e5cb-c99d-84d6-1e51-d8c110e21301.png)

## MagicAnimateで画像を動かす
上で生成した画像をさらにMagicAnimateで動かしてみます。
MagicAnimateには[Windows版のフォーク](https://github.com/sdbds/magic-animate-for-windows)があるのでそちらを使用します。

Readmeのインストールの手順に従ってインストールを行ってください。

Python Processer TOPで先ほど生成した画像から動画を生成するよう実装します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/255882e2-3f2e-0008-89bb-f6643c5502d1.png)

クックが完了するとOutputから動画を確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/d6dd134a-47e8-b988-b6e2-f59b21d140fd.png)

若干目の部分などおかしいですが走っているアニメーション動画を生成できました。
![ezgif.com-video-to-gif-converted.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/2ce5f4a4-34e5-2c02-22d0-783b605e3eb3.gif)
![ezgif.com-video-to-gif-converted (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3492828/b4450262-20c4-9b40-4ea1-00c5fa3f0a82.gif)


## さいごに
diffusersをPDG上で使う方法についてでした。
- カスタムモデルの変換
↓
- 画像生成
↓
- アニメーション生成

のフローをPDGで作ってみました。ここからさらに、
- 複数モデルから画像を出力する
- Wedge TOPによってプロンプトテキスト、ステップ数などにバリエーションを作る
- アニメーションソースを複数にする

など、いろいろとカスタマイズすることができそうです。

MagicAnimateは重すぎて、自分の環境では本記事のデモを動かすだけでめちゃめちゃ時間がかかりました。。
あと本題とは関係ないですが、記事を書きながら初めて`Python Vertual Environment TOP`を使いました。Houdini上で仮想環境のセットアップから行えるのはかなり便利でした。