はじめに
今回は、AI画像生成が実際にどのような工程で進むのかを確認する簡単な練習として、1枚のキャラクター画像を制作しました。
衣装、姿勢、背景、構図、表情などを一度に変更するのではなく、いくつかの工程に分けて少しずつ調整しました。途中ではDWPoseによる姿勢抽出、AnyLineによる輪郭処理、Maskを使った局所修正、Upscaleによる高解像度化なども試しています。
この記事では、その制作過程をもとに、ComfyUIを使ったAI画像生成のおおまかな流れと、それぞれの処理がどのような役割を持つのかを説明します。
元画像、参考画像、生成結果は掲載せず、各工程で行った処理を文章で紹介します。
ComfyUIとWorkflow
ComfyUIは、画像生成や画像処理をノード単位で組み立てる環境です。各ノードは、画像の読み込み、前処理、モデルの読み込み、サンプリング、画像合成、拡大、保存などの処理を担当します。ノード同士をLinkで接続し、処理とデータの流れを構成したものがWorkflowです。
ノード間では、処理結果となるデータが受け渡されます。代表的なデータ型には、画像を表すIMAGE、マスクを表すMASK、拡散モデル内部の潜在表現を扱うLATENTなどがあります。接続できる入出力も型によって決まります。
ComfyUIには標準で含まれるノードと、追加で導入するカスタムノードがあります。今回使ったDWPose EstimatorやAnyLineは、入力画像から後続処理に利用する条件画像を作るプリプロセッサです。DWPose Estimatorは姿勢画像を、AnyLineは線画を出力します。
Workflowを分けておくと、入力画像の差し替え、前処理の設定変更、画像合成だけの再実行といった作業を個別に行えます。今回は、すべての処理を単一のWorkflowにまとめず、工程ごとに中間画像を保存し、次の工程へ渡しました。
制作フロー
元の参考画像をR0とし、その後の工程をC1からC7までに分けました。C1からC4で人物、姿勢、背景、構図を作り、C5以降で輪郭、表情、解像度を調整しています。
| 工程 | 内容 | 主に使用した処理 |
|---|---|---|
| R0 | 人物の基準となる参考画像 | 参照元 |
| C1 | 衣装の再設計 | 参考画像を用いた画像編集 |
| C2 | 姿勢の抽出 | DWPose Estimator |
| C3 | 人物、姿勢、物体関係の統合 | Seedreamによる複数画像編集 |
| C4 | 背景と構図の再構成 | 参考画像とプロンプトによる画像編集 |
| C5 | 全体の見た目を調整 | 線画を使った全体再生成(不採用)、AnyLine、Invert、Multiply |
| C6 | 表情の局所修正 | Mask、Inpaint Crop、Denoise |
| C7 | 高解像度化 | Real-ESRGANのアニメ向け4倍モデル、Lanczos |
この番号は説明のために付けたもので、ComfyUIのノード名ではありません。C3の統合にはSeedreamを使用し、C2およびC5からC7の処理はComfyUIで行いました。
C1:衣装の再設計
最初に衣装を変更しました。基準画像にあるキャラクターの特徴を残しながら、別の参考画像をもとに衣装を再構成する作業です。
プロンプトだけで衣装全体を作り直したときは、衣装と一緒に体格や肩幅も変わりました。元画像では手と衣装が重なっていたため、袖や胸元を変更すると手の形まで崩れることもありました。参考画像を追加した場合も、参考画像側の体型やシルエットが衣装と一緒に反映されることがあります。
そこで、全体の方向を決めた後、肩と襟、胸元の順に範囲を分けて修正しました。一度に変更する範囲を絞ると、衣装の変更に伴って人物のほかの部分が変わっていないか比較しやすくなります。
この工程では、特定の機能よりも編集範囲の分け方を優先しました。後の工程で姿勢や背景を変更するため、C1では人物と衣装の基準になる状態までを作っています。
C2:DWPoseによる姿勢抽出
次に、動作参考画像から姿勢を取り出しました。目標としたのは、片手で頬を支え、もう一方の手でペンを持つ姿勢です。
DWPose Estimatorの役割
DWPose Estimatorは、入力画像から人物の姿勢を推定し、身体各部や手指の位置を骨格画像として出力するプリプロセッサです。今回の骨格画像には、頭、肩、肘、手首、手指の位置が線と点で表されていました。
出力されるのは、後続処理へ渡すための条件画像です。この骨格画像は、対応するControlNetの条件として利用できます。出力された骨格画像は、OpenPose系のControlNetなどで姿勢条件として利用することもできます。今回はPose ControlNetには渡さず、複数の参考情報の1つとしてSeedreamへ入力しました。
姿勢の抽出と、その結果を画像生成や編集へ反映する処理は別です。骨格画像をどのモデルへ渡し、ほかの条件とどう組み合わせるかによって、姿勢の反映結果も変わります。
骨格画像に含まれない情報
DWPoseの出力には、人物の姿勢を表すキーポイントが含まれます。ペン、ノート、机の形や位置は骨格画像に含まれません。手首や指先の座標が得られても、その指がペンを握っているのか、ペンの横に置かれているのかまでは表現されません。
実際の生成結果でも、指の本数は合っていたものの、ペンを握るというより指の間に置いているように見える状態がありました。今回は、人物の姿勢と、手と物体の接触関係を別の情報として扱いました。
C3では、身体と手指の位置をDWPoseの骨格画像から参照させ、手とペン、ノート、机の関係は動作参考画像とプロンプトで補いました。
C3:複数の参考情報を統合する
C3では、人物と衣装の画像、動作参考画像、DWPoseの骨格画像をSeedreamへ入力しました。それぞれの画像から参照する情報は異なります。
| 入力 | 参照した内容 |
|---|---|
| 人物・衣装の画像 | 人物の特徴とC1で決めた衣装 |
| 動作参考画像 | 手、ペン、ノート、机の接触関係 |
| DWPoseの骨格画像 | 身体と手指の位置 |
| プロンプト | 場所、物体の種類、位置関係 |
最初の統合では上半身を中心に作成しました。その後、下半身まで画面に含めたところ、脚が短くなり、机の形も崩れました。骨格画像があっても、人物と机の相対位置や、脚が机の内側に入る構造までは確定していません。
修正時には、学校で使う1人用の机であることと、両脚が机の下へ自然に入ることを文章で指定しました。脚の追加だけを指示せず、脚と机の位置関係まで記述しています。問題が下半身と机の周辺にあったため、その部分を中心に再編集しました。
複数の参考画像を入力しても、モデルが各画像から必要な要素だけを切り出して使うとは限りません。今回は、人物の外見、姿勢、物体関係を別々の画像から参照させ、画像だけでは不足する関係をプロンプトで補いました。
C4:背景と構図の再構成
C4では、教室、窓の外の桜、窓際の席を追加し、人物と机が収まるカメラ構図を決めました。教室の表現を整え、桜を配置し、席を窓際へ移した後、人物、机、窓の画面内の位置と大きさを見ながら画角を調整しています。
背景を変更すると、人物や机の配置にも影響します。窓を大きくすると人物の位置や余白が変わり、机を手前へ出すと人物の下半身との関係も変わります。何を変更した結果として別の部分が崩れたのかを確認できるように、要素を順に追加しました。
人物と構図が安定した時点の画像をC4として保存し、後処理の基準にしました。C5以降は、C4をできるだけ描き直さず、輪郭、表情、解像度の調整に移りました。
C5:全体調整
線画を使った全体再生成
最初に、C4の構図を残したまま、画像全体の表現をアニメCG風にそろえる処理を試しました。元画像から線画を作り、その線画を構造条件として、アニメ系のモデルで全体を再生成する方法です。
線画には、人物、机、窓などの輪郭と配置が残ります。線画だけでは、色や陰影、顔の細部までは保持できません。線画を条件にして再生成すると、大まかな形を参照しながら、残りの情報を生成モデルが描き直します。
結果として、人物と机の位置はある程度維持されました。顔つきはC4から変わり、元の人物の特徴は残りませんでした。線画で固定できたのは主に輪郭と配置であり、人物の同一性までは固定できませんでした。
この出力へ追加修正を重ねず、C4へ戻りました。構図を保つ目的には線画を利用できましたが、人物を描き直さずに全体の印象を整えるには、別の処理が必要でした。
AnyLineによる輪郭合成
AnyLineは、入力画像から物体の輪郭や細部を線画として抽出するプリプロセッサです。出力した線画は、対応するControlNetなどへ渡し、元画像の構造を参照した条件付き生成に利用できます。
今回は、AnyLineの出力を生成条件として使用せず、合成素材としてC4へ直接重ねました。画像全体を再生成しないため、人物の顔や色はC4の状態を維持できます。
InvertとMultiply
AnyLineから得た画像は、黒い背景に白い線でした。これをInvertで反転し、白い背景に黒い線へ変換しました。その後、C4の画像へMultiplyで重ね、合成強度を35%に設定しました。
Multiplyでは、白い部分は元画像への影響が小さく、黒い部分は元画像を暗くする方向に働きます。そのため、白い背景に黒い線を持つ画像を重ねることで、元画像の色を大きく変えずに輪郭を追加できます。
今回は強度を35%に抑え、人物、髪、衣装、机、窓の線を薄く重ねました。生成モデルによる再描画は行っていないため、C4の顔や色、構図はそのまま残しています。
C6:MaskとInpaintによる局所修正
C6では、少し眠そうで、授業中にぼんやりしている表情へ調整しました。変更したのは目、眉、口の周辺です。処理にはMask、Inpaint Crop、Denoiseを使用しました。
Maskが決める範囲
Maskは、後続処理へ修正対象の範囲を渡すデータです。今回のInpaintでは、目、眉、口の周辺をマスクし、髪、顔の輪郭、衣装、背景を修正対象から外しました。
局所修正では、マスクの境界も結果に影響します。修正範囲が狭すぎると周囲とのつながりを作る余地がなくなり、広すぎると残したかった部分まで描き直されます。目や口の形と、その周辺をどこまで含めるかを合わせて調整しました。
Inpaint Cropが切り出す範囲
Inpaint Cropは、マスク周辺を画像から切り出し、後続のInpaint処理へ渡すためのノードです。画像全体を同じ大きさで処理せず、修正箇所とその周囲へ処理を集中できます。
マスクは変更対象を決め、Cropは後続処理へ渡す画像範囲を決めます。目と口だけをマスクしていても、表情を周囲になじませるには頬や鼻、髪との位置関係が必要になるため、Crop側には周辺の情報も含めます。
Denoise 0.25
Denoiseは、入力画像をどの程度作り直すかを調整する値です。同じモデルと条件で比べると、値を小さくした場合は入力画像との差が小さくなり、値を大きくした場合は生成側の変化も大きくなります。
今回は0.25に設定しました。C5までの形を残しながら、目、眉、口の表現だけを少し変えるためです。Maskで修正範囲を制限し、Denoiseでその範囲内の変化量を抑えました。
C7:Real-ESRGANとLanczosによる高解像度化
最後に、1280×1600の画像を2560×3200へ拡大しました。アニメ画像向けのReal-ESRGAN 4倍モデルで5120×6400へ拡大した後、Lanczosフィルタで最終的な2560×3200へ縮小しています。
アップスケールモデルによる拡大
ComfyUIでモデルによる拡大を行う場合、Load Upscale Modelで拡大モデルを読み込み、Upscale Image (Using Model)へ入力画像とモデルを渡します。今回は、アニメ画像向けのReal-ESRGAN 4倍モデルを使用しました。
Real-ESRGANは、学習済みモデルを使って高解像度側の細部を推定します。元画像に存在した細部をそのまま復元する処理ではないため、入力画像の状態によっては輪郭や模様の見え方も変わります。C6までに構図と表情を確定し、最後に全体を確認しながら適用しました。
Lanczosによるサイズ調整
使用したReal-ESRGANモデルの出力倍率は4倍です。必要な最終サイズは2倍だったため、4倍の出力をLanczosで2560×3200へ縮小しました。
Lanczosは、周囲の画素から新しい画素値を計算するリサンプリングフィルタです。画像の内容を意味的に描き直さず、指定した幅と高さへ変換します。今回は、モデルによる拡大と最終サイズへのリサイズを別々に行いました。
C7では拡散モデルによる再生成を行っていません。人物、構図、表情の変更はC6までで終わり、最後は解像度と見え方だけを調整しました。
まとめ
今回の制作では、衣装、姿勢、物体関係、背景、構図を決めた後、輪郭、表情、解像度を調整しました。DWPose、AnyLine、Mask、Denoise、アップスケールモデルは、それぞれ扱う情報と変更範囲が異なります。
線画を使った全体再生成では人物の特徴が変わったため、保存していたC4へ戻り、生成を伴わない輪郭合成へ切り替えました。工程ごとに中間結果を残していたことで、前の状態へ戻り、必要な処理だけをやり直すことができました。
参考資料
ComfyUI Documentation: Workflows
ComfyUI's ControlNet Auxiliary Preprocessors
ComfyUI Inpaint Crop and Stitch
ComfyUI Documentation: Image to Image Workflow