ComfyUIでループ(For Loop)を使ってみよう(execution-inversion-demo-comfyui)
このnoteではカスタムノードexecution-inversion-demo-comfyui
でFor Loopを使った、2つのワークフローを紹介します。
1つ目は複数マスクの合成で、2つ目はCFGの値をリストとして生成します。
(注意)
本家のノードには一部のノードに不具合があるので、フォークしたものを使います。
本家: https://github.com/BadCafeCode/execution-inversion-demo-comfyui
フォーク: https://github.com/Robonau/execution-inversion-demo-comfyui/tree/main
ワークフローはこちら。
マスク合成: https://github.com/ippan-orc/comfyui_workflow/blob/main/workflows/demo/for_loop_mask_composite.png
CFG数値のリストを生成: https://github.com/ippan-orc/comfyui_workflow/blob/main/workflows/demo/for_loop_cfg_asc.png
[ワークフロー読み込み方]
ワークフロー画像をドラッグし、ComfyUIのあるタブでホバーするとタブに移動するので、ComfyUIのアプリ画面内でドラッグを離します。
ここから解説していきます。
まずは、マスク合成ワークフローです(図1)。全体を見てみましょう。
このワークフローは黒のマスクに4つのマスクを合成して1つのマスクにするワークフローです。
ノードを見ると、Accumulation、remainingという、見慣れない単語が見られます。
これらは、
Accumulation=配列
remaining=繰り返す数(ノード入力側)/ループの残り回数(ノード出力側)
と考えると良さそうです。
また、value1, 2, 3, 4 とありますが、これは変数として考えると良さそうです。ループ部分は、For Loop Open/Closeで囲まれ、Flow Controlでつながれています。
それでは、各々のノードを見ていきましょう。
[青ノードの部分](図2)
このノードでは黒画像をマスクとして読み込み、value1の初期値としてFor Loop Openノードのinitial_value1に与えています。value1は最終的に合成されたマスクが格納されます。
[赤ノードの部分](図3)
このノードでは、合成するマスクを配列として、For Loop Openのinitial_value2に渡します。
MakeListでマスクの配列を作成し、Accumulationに変換後、For Loop Openノードのinitial_value2に入力します。
[紫ノードの部分(図3)]
また、For Loop Openノードのremainingには、Accumulation Get Lengthノードで配列の数を取得し、入力します。入力側なので、remaining=繰り返す数となります。
[緑ノードの部分](図4)
図4のノードは少し複雑に見えます。実際のところは難しくありませんが、ノードの線の色も同じような色でわかりにくいです。実際に値を変更している部分とそうでない部分を分けてみましょう。
まずはシンプルな方から見ていきます。図5は値を変更していない部分です。
For Loop Open/Close間でflow_control, value2は直接つながれています。また、initial_valueが入力されている、それぞれのvalueは変更しない場合でも接続する必要があります。
図6は実際に値を変更している部分です。
value1からの値を変更し、initial_value1へ入力しvalue1を更新、をremainingの数だけ行います。このワークフローでは実際には、MakeCompositeノードで空のマスクに配列内のマスクを順次合成していきます。MakeCompositeノード以外の部分を見ていきましょう。
Accumulation Get Itemノードは、配列から値(今回は合成するマスク)を取り出します。配列から値を取り出すには、indexが必要となります。indexとは、配列の値に割り振られた番号です。これはAccumulation(配列)では0から始まります(0-indexという)。indexを使うためにremainingを利用しましょう。出力側のremainingはループの残り回数です。remainingは入力した数値Nから1まで出力するので、remainingから1を引いた値をindexとして使用します。
ループ間で処理の順序が重要な場合は、remainingの出力は1からNではなくNから1であることに注意してください。今回は順序は重要でないのでこのまま続けます。
では、indexのためのノードを接続しましょう。For Loop OpenノードのremainingをMath Expressionノードのaに入力し、式"a-1"を定義します。出力をAccumulation Get Itemノードのindexに入力します。他のノード接続は図6を参考にしてください。
これでFor Loopは完成です。次はFor Loop後の出力について見ていきましょう(図7)。
このノードは、value1(合成されたマスク)を画像に変換し、画像を表示するノードに接続するだけです。これで最初に紹介したワークフローの説明は終わりです。
次に、もう1つのワークフローを紹介します(図8)。
CFGの値をリストとして生成し、それを使って画像を生成します。
このワークフローは、CFG6~8を0.5刻みで昇順に生成します。
For Loop Openノードのremainingの出力は、ループごとに5, 4, 3, 2, 1と降順に減少します。このremainingの出力値を昇順番号の生成で利用します。具体的には、まずremainingの出力から降順配列を作成し、別のFor Loop Openノードのremainingの出力をindexとして利用し、末尾から値を取得していきます。以下、各ノード部分の詳細を説明します。
[赤い部分]
降順の配列[4, 3, 2, 1, 0]を作成。
remaining出力のみを使う場合は、initial_valueへの入力は不要。
remainingの値を配列に追加するために、remainingをAccumulateノードのto_addへ接続。配列の受け取り/更新のために、Open/Closeノードのvalue1/initial_value1につなぐ。
[青い部分]
生成した配列から、昇順の値を取得する。
式 6+(a/2) でCFGの値を計算し、配列[6.0, 6.5, 7.0, 7.5, 8.0]を作成。
Accumulation to Listで配列をリストに変換。
[緑の部分]
画像生成部分はデフォルトノード。
CFGの数値であるリスト出力をKSamplerのcfg入力につなぎ、生成する。
これでこのワークフローの説明は終わりです。
今回は2つのワークフローを紹介しました。
気になった点としては、デフォルトで降順、Open/Close間の配線が複雑、という点があげられます。
昇順にするにはループのためのノードを追加する必要があり、ワークフローが肥大化します。Open/Close間では、0-indexにするためにノードが1つ増えます。
また、線の色が同色なので視認性が悪かったり、ループ前後でのAccumulation-List間の変換が冗長に思えます。
更に細かいことを言えば、For Loop Open/Closeノードで、各initial_valueとvalue, remainingの位置が横並びでないことが少し気になります。
便利なノードなので、今後の改善に期待したいです。
ここから先は
この記事が気に入ったらチップで応援してみませんか?