StableDiffusion ComfyUI

RunPodではtemplateをComfyUIにすることで自動的にインストールされます
自前環境でもgithubからクローンすればよい

おそらく、

  • 8080:FileBrowser
    JupyterLabよりファイル移動が楽(ユーザ名:admin, パスワード:adminadmin12)
  • 8188:ComfyUI
  • 8888:JupyterLab
    主にターミナルを使用するとき使うと思う

ComfyUIの見た目

workflow

ComfyUI/user/default/workflows/内にある

プロンプト

  • 重み

プロンプトの重みはリスト内の位置で管理でき、先頭にあるものほど重みが高く、生成された画像に反映されやすくなります。
タグの重み付け
(prompt: 1.5)
0.5~1.5の範囲で設定

上のパズルピースのマークの"Manager"を押下して、下図のメニューから"Model Manager"を開きます

画像比較

“Manager"メニューから"Custom Nodes Manager"を開いて、rgthree-comfyをインストール

Image Comparer (rgthree)を使って

顔修正

“Manager"メニューから"Custom Nodes Manager"を開いて、ComfyUI Impact PackComfyUI Impact Subpackをインストール


次に同じ"Manager"メニューから"Model Manager"を開いて、face_yolov8n_v2 (bbox)ViT-B SAM modelをインストール

ここまでやったら、RunPodに行ってReset Podする

追加するのはFaceDetailerUltralyticsDetectorProviderSAMLoaderの3つ

オプションの説明

  • guide_size:領域の短い辺の最小値。guide_size$=512$で、領域が縦500,横400の場合、横が512になり、アスペクト比を維持したまま縦も拡大される。この例なら$500\cdot512/400=640$なので、縦640,横512
    $\min(w,h) $$ \begin{align} \min(w,h)&\to x_{guide}\\ \max(w,h)&\to \max(w,h)\cdot \frac{x_{guide}}{\min(w,h)} \end{align} $$
  • guide_size_forguide_sizeが判定する領域の定義。bboxは顔の大きさ、crop_regionは顔を含んで大まかに切り取られた領域
  • max_sizeguide_sizeによって拡大された長い辺の最大値。先の例で言えば、max_size$=600$なら、縦640でmax_sizeより大きいので600に強制され、縦600,横512となる
  • seed,steps,cfg,sampler_name,scheduler,denoise:K samplerと同じ。denoiseはノイズ除去
  • feather

公式tutorial

高解像(UpScaler)

“Manager"メニューから"Model Manager"を開いて、4x-AmimeSharp4x-UltraSharpとか好きなものをインストール
4倍の解像度に拡大するという意味で4xだと思う

ComfyUIを再起動

VAE decode後にLoad Upscale ModelUpscale Image (using Model)を噛ませて以下のようにつなぐ

画像からプロンプト推論

参考

“Manager"メニューから"Custom Nodes Manager"を開いて、ComfyUI-Custom-Scriptsをインストール

custom_nodesディレクトリに移動

cd runpod-slim/ComfyUI/custom_nodes

クローン

git clone https://github.com/pythongosssss/ComfyUI-WD14-Tagger

依存モジュールをComfyUI用の仮想環境にインストール

source /workspace/runpod-slim/ComfyUI/.venv-cu128/bin/activate
pip install -r /workspace/runpod-slim/ComfyUI/custom_nodes/ComfyUI-WD14-Tagger/requirements.txt

タグ推論モデルを格納するmodelsディレクトリを作る

mkdir /workspace/runpod-slim/ComfyUI/custom_nodes/ComfyUI-WD14-Tagger/models/

モデルをダウンロード
tokenはここで作る

from huggingface_hub import hf_hub_download, snapshot_download
import os
repo_id="SmilingWolf/wd-eva02-large-tagger-v3"
name="model"
path="/workspace/runpod-slim/ComfyUI/custom_nodes/ComfyUI-WD14-Tagger/models/wd-eva02-large-tagger-v3"
token=""
filepath = hf_hub_download(repo_id=repo_id,filename=f"{name}.safetensors",local_dir=path,token=os.getenv(token))

podを再起動

WD4 Taggerのオプション

  • model:使用するモデル(ComfyUI/custom_nodes/ComfyUI-WD14-Tagger/models/
  • threshold:認識したタグを出力する閾値。大きいほど関連性の高いタグが出力される。
  • character_threshold:キャラクタータグの閾値。キャラの断定が難しい構図だったり、そもそも学習が足りてないキャラは出ない

ガベルが重い姉御で試した

出力されたタグにキャラクタ名を追加して生成した

ControlNet

promptが文字による制御だとすると、ControlNetは画像による制御
参考:

ComfyUIを再起動

こんな感じでプロンプトと合流させる

キャニーの部分を他の方法に変えることもできる↓

Preprocessor 抽出する情報 使う場面
Canny 輪郭(エッジ) 元画像の形をそのまま反映したい
OpenPose 人物の骨格・ポーズ ポーズを維持しつつ見た目を変えたい
Depth Map 奥行き・距離情報 背景の立体感を残したい
M-LSD Lines 建物の直線構造 建築物の形だけ活かしたい

“ControlNetを適応"ノードのオプション

  • 強度:解析画像の影響度。値が大きいほど元画像の形を維持(0.5~1.2辺りが妥当?)
  • 開始パーセント:反映開始のタイミング。0.0 が開始時、値が大きいほど後半から適用
  • 終了パーセント:反映終了のタイミング。1.0 で生成完了まで反映、短くすると後半は自由生成

開始、終了というのはKサンプラーのステップ数のことだと思われる
ステップ数30で、開始パーセント0.5なら、15ステップ目からControlNetが適応され始める

Canny

輪郭の内側などの調節?
こいつを変更してみる↓

red_eyes, black_hair, slit_pupils, grey shirt

ポジティブをこんなもんにして、ContolNetと組み合わせて生成

OpenPose

プラグインをインストールしたのにOpenPose poseノードが無くて困ったが、バージョンを選びなおしたりPod自体を再起動したら治った

こんな感じ
モデルはall in oneのもの使っているので、変える必要はない

入力パラメータ 説明 パラメータオプション
images 入力画像 -
detect_hand 手の検出の有無 enable / disable
detect_face 顔の検出の有無 enable / disable
detect_body 体の検出の有無 enable / disable
resolution 出力画像の解像度 -

resolutionは縦横で短い方のピクセル数。resolution=512で1640x984なら853x512で出力される
元画像が1024pxくらいあっても512くらいにした方が反映されやすい気がする
本来は元画像と同じくらいの解像度が良いっぽい



ポーズに関するプロンプトを省略してControlNetに丸投げする

1girl, solo, jacket, short_shorts, fang, clear_sky, full_body, upper_teeth, gold_eyes, gold_hair, navel, slit_pupils, grey_shirt, looking_at_viewer

LoRAを適応して絵柄を変えても大体同じポーズになる。
実用としては丸投げするよりもプロンプト側で大まかに同じポーズを指定したほうが近づく

全然画像のポーズが認識できないと感じたら、open-pose-editorなどを使って手作業で作るという手もある

カラーマスク

キャラクターごとに位置、プロンプトを個別指定する
複数キャラを扱うときに使う
参考

“Manager"メニューから"Custom Nodes Manager"を開いて、ComfyUI Inspire Packをインストール

Podを再起動

カラーマスクのみ

Regional Conditioning By Color Mask (Inspire)ノード、条件付け(組み合わせ)ノードを使って下図のようにつなぐ

mask_colorは任意で指定する

Regional Conditioning By Color Mask (Inspire)ノードは以下のように値を変更した

strength(プロンプトの重み):0.7
dilation(カラーマスクのグラデーション、領域拡大):0.0

カラーマスクは色コードを合わせながらペイントなどで作成する

テキトーに塗りつぶしてみた

ベース

3girls, trio, 3d, tracen_school_uniform, general, from above, stage, horse_ears, horse_tail, looking_at_viewer, masterpiece, best quality, amazing quality,

vivlos_\(umamusume\),laugh, long_hair, twintails, purple_eyes, brown_hair,

verxina_\(umamusume\), smile, long_hair, blue_hair, purple_eyes,

cheval_grand_\(umamusume\), blush, short_hair, hat,

比較的まともな出力でもあまり良くない
心霊写真みたいになる
顔の距離が近いと、髪型などがまぜこぜになる

カラーマスク+ControlNet

カラーマスク↓

OpenPose↓

数値、プロンプトは同じ
シュバルグランが出てこない

参考内で使っていたCN-posetestは適当なラフでポーズ指定できる
ここでは棒立ちだが

プロンプトと値を調節すると少しだけましになったか?

3girls, trio, 3d, tracen_school_uniform, sky, grass,v_sisters, horse_ears, horse_tail, horse girl, looking_at_viewer, masterpiece, best quality, amazing quality,

strength:0.55

verxina_\(umamusume\), smile, blue_hair, purple_eyes,

strength:0.75

(cheval_grand_\(umamusume\): 1.4), brown hair, blue_eyes, streaked hair, peaked_cap, ears through headwear

strength:0.75

vivlos_\(umamusume\),laugh, twintails, purple_eyes, brown_hair,

立ち位置の固定はできるがキャラクターのビジュアルが混ざるのであまり良くない

プロンプトコントロール

comfyui-prompt-control

“Manager"メニューから"Custom Nodes Manager"を開いて、ComfyUI Prompt Controlをインストール
インストール後Manager内では未インストールと表示される

githubからインストールしたほうがよい
cloneしてComfyUIのvenvに入ってpip insatall -r requirements.txt

Podを再起動


v2.1.3~v3.0.0-beta.3を使う場合、ソースコードにバグがあるので手動で修正する
Issue
comfyui-prompt-control/prompt_control/attention_couple_ppm.py
119行目と146行目の以下の条件文を置き換える

if self.kv["k"] is None

if len(self.kv["k"]) == 0

こんな感じでつなぐ
プロンプト内でLoRAを指定できるのでLoRAを読み込むノードが要らないが、LoRAを変更したときの読み込みが少し遅い

プロンプトの記法

A1111に近い記法で書ける。A1111使えばというのは野暮
参考元に書いてあること日本語にしただけ

スケジューリング式

一単語の中で以下のように書く

a [red:blue:0.5] cat

これは、推論ステップ中にプロンプトを変更する式で、
0.5は割合を示す
つまり、30ステップの推論であれば、前半の15ステップはa red cat
後半の15ステップはa blue catとなる

なお、2以上の値を設定すれば割合ではなくステップ数で切り替えられえる
a [red:blue:2] catなら2ステップ目からa blue catに切り替わる

a [red::0.5] catのようになにも入れなけばa red cata catとなる
逆の場合はa [:red:0.5] catだが、a [red:0.5] catと、手前のコロンを省略してもよい

入れ子構造も可能で、以下の場合なら0%~50%までa red cat、50%~70%までa blue cat、70%~100%までa catに変化していく

a [red:[blue::0.7]:0.5] cat

ただ、以下の複数個用の構文を使用したほうが分かりやすい

a [red:blue::0.5,0.7] cat

以下のように記述すると交互にプロンプトが変化する
10%ごとにプロンプトがabで切り替わる

[a|b:0.1]

LoRA読み込み

プロンプト内でLoRAを読み込むには、以下のように記述する
ファイル名を指定する。拡張子は付けても付けなくても可
末尾にある1はLoRAの重み

<lora:examplelora:1>

“loras"ディレクトリ内のexamplelora.safetensorが読み込まれる
“loras/sdxl/sdxlexample.safetensor"のような子ディレクトリに格納されたファイルも再帰的に読み込まれるため、pathの記述は不要
ただし、同じファイル名のloraがあった場合、先に見つかった方が読み込まれる
それを避けたい場合はファイル名を重複しないようにするか、以下のようにpathで指定する(“loras"ディレクトリからの相対パス)

<lora:sdxl/sdxlexample:1>

以下のようにスケジューリングも可能
推論ステップの半分までpartialoraが適応される

[<lora:partialora:1>::0.5]

プロンプトの重み付け

重みの記述がない場合、重みは1
重みが0の場合、完全に無視される
以下のように記述する

(dog :1.5), (cat :2)

関数の組み合わせ

2つ以上の関数を使う場合はANDを使って連結する

スタイル

以下のように記述する

STYLE(comfy, length)

引数1(重みの解釈)

  • comfy
  • comfy++
  • compel
  • down_weight
  • A1111
  • perp
    引数2(正規化)
  • 引数なし
  • length
  • mean

デフォルトはSTYLE(comfy)

COUPLE

x軸範囲でプロンプトを変化させる

sky, grass,
FILL()

COUPLE(0 0.2)
1girl, solo, vivlos_\(umamusume\),
long_hair, twintails, purple_eyes, brown_hair,
laugh, standing

COUPLE(0.45 0.55)
1girl, solo, verxina_\(umamusume\),
long_hair, blue_hair, purple_eyes,
smile, standing

COUPLE(0.8 1.0)
1girl, solo, cheval_grand_\(umamusume\), 
short_hair, blue_eyes, hat, 
blush, standing

LoRAをそれぞれに適応させればマイナーキャラもいけたり(調整は必要だが)