見出し画像

ComfyUIで顔のin-paintingマスクを作る (3種)

こんにちは。季節感はどっか行ってしまいました。
今回も地味なテーマでお送りします。

顔のin-painting

Midjourney v5やDALL-E3(とBing)など、高品質な画像を生成できる画像生成モデルが増えてきました。
新しいモデル達はプロンプトを少々頑張るだけで素敵な構図の絵を生み出してくれます。StableDiffusion 1.5でよくある真ん中に美少女どーん、みたいな画像だけではありません。

DALL-E3ぽん出し。
何やら不謹慎ですが、最近トップガンマーヴェリックを観たせいだと思います

構図出しが進化した一方で画風や筆致はあまり制御できないので、好みの絵柄にするにはimg2imgなりin-paintingなり後処理が必要になってきます。絵柄の印象をもっとも左右する要素は人物の顔の描き方でしょう。

顔をin-painting


ComfyUIで顔のみ修正する場合はImpactPack https://github.com/ltdrdata/ComfyUI-Impact-Pack のDetailerノードが便利です。部分修正に特化したin-paintingという趣で、指定した領域の周辺を拡大しimg2imgしたあと再合成してくれます。

我らの強い味方Detailer

#1 手動でマスクを指定する

Detailerノードは修正する領域をSEGSで受け取ります。この領域を指定する一番簡単かつ確実な方法は、Load Imageノードから手作業でマスクを作る方法です。

画像の上から右クリック→Open in MaskEditor
顔を塗りつぶす作業は独特の背徳感があります

in-painting自体は以下のようなワークフローになります。
Load Imageノードから出てくるのはMASKなので、MASK to SEGSノードでSEGSに変換してやります。

MASKからのin-painting

うまくいきました。

高波が来たら一発アウト

確実な方法ですが、画像ごとに毎回手作業が必要になるのが面倒です。


これらを自動化することはできないでしょうか?
この記事の残りの部分では、顔を自動検出してマスクを生成する手法について、いくつか紹介していきたいと思います。例によって我流です。

#2 オブジェクト検出を使う

YOLOv8をベースにしたオブジェクト検出を使って自動で顔を検出する方法です。

オブジェクト検出で全自動in-painting

ちょっとセットアップが面倒な点を乗り越えてしまえば、あとは全自動です。楽ちん。

枕が侵食されちゃいました

このオブジェクト検出は高い精度で顔を検出してくれます。ただいくつか課題もありそうです。

  • オブジェクト検出モデルが写真中心に学習されているため、塗りが平坦だったりデフォルメが効いたイラストだと検出できないことがある

  • 境界が四角であることにより周囲の巻き込み事故を起こしやすい

  • 人物の顔が直立でない場合(上記のように寝転がっている場合など)はin-paint後の顔が歪んだり崩壊することがある

3つめは手動の場合も共通する問題ですね。
例えばこんな感じです。in-paintingに使うモデルがSD1.5で、denoiseが高いとよく起きます。

部分的にホラー

次に紹介するボーン検出を使った手法であれは、これらの課題を解決することができます。

#3 ボーン検出を使う

ボーン検出は画像から人体の関節点(首, 肩, 肘, etc.)や特徴点(目, 鼻, 耳, etc.)の座標を見つける技術です。

ControlNetでおなじみのアレ

拙作NegiTools https://github.com/natto-maki/ComfyUI-NegiTools にはボーン検出の結果をJSON文字列で取得するOpenPose to Point Listノードがあります。これを使って顔のマスクを生成してみましょう。

※ 他の実装で代用可能ですが、ControlNet用に画像しか出力しないものは使えませんのでご注意ください。

イラストでボーン検出する

まずはイラスト画像で確実にボーン検出するための仕込みをします。ボーン検出に使われているOpenPoseモデルはYOLOv8以上にイラストに弱く、そのまま通しても「人体なし」となることが多いです。

この対策として、リアル系モデルか、リアル寄りのアニメモデルを使って軽くimg2imgをかけてからOpenPoseの検出に進みます。

複雑でごめんね

ボーン検出は短辺512ピクセルに縮小してから処理しますので、img2imgも元画像を半分に縮小してから実行しています。
変換後の画像はこんな感じ。

なんかドザエモン感ある

リアル寄りアニメモデルを使ったのであまり変化していないですね。でもOpenPoseにはこれで十分です。

このやり方だと、img2imgの過程で形が変化した部分はボーン座標がズレてしまいます。とはいえ顔の位置と回転角度を特定する程度の用途であれば問題になりません。

顔の座標と回転角度を計算する

続いてボーン座標から顔の座標を計算します。あわせて顔の回転方向も計算してしまいましょう。

顔の中心座標は鼻・目・耳のボーン座標の平均値とし、半径は中心座標から各ボーン座標までの距離の最大値とします。また回転角度は、首の関節点と顔中心がなす角度に基づいて決めればよさそうです。

というわけでこうなります!

いやはや

ちょっとしたロジックを必要とするため、下手にノードを組み合わせて頑張るよりプログラムを書いた方が簡単に済みます。というわけでNegiToolsからString Functionノードを使用しました。このノードはpythonスクリプトで文字列を加工できるため、こういう状況では非常に便利です。

・・・はい、わかってます。
面倒過ぎですよね。
というわけで、NegiTools v0.3.3にDetect Face Rotation for Inpaintingノードを追加しました。上のワークフローをまんまノード化したものです。

回転してin-painting

それでは後段のワークフローを組みましょう。

Detect Face Rotation for Inpaintingノードの計算結果に基づいて、顔の角度の逆方向に画像を回転し(顔が正立するように回す)、その後in-paintingして回転方向をもとに戻せばできあがりです。

2024.03.07追記: 画像を回転するImage Rotateノードは https://github.com/WASasquatch/was-node-suite-comfyui  を使用しています。

ボーン検出の後ろにつなぎます

途中の画像出力から、正立した状態の顔に対してin-paintingできていることがわかります。境界を円形にしたことで余計な領域を巻き込んでもいません。
最終結果も上々です。

ここにたどり着くまでが長かった

この方法は強力だと思っていますが、画像全体を回してDetailerノードでin-paintingするという処理の都合上、人物が1人でないと適用できない点が最大のネックです。

まとめ

ComfyUIで顔をin-paintingするためのマスクを生成する手法について、手動1種類 + 自動2種類のあわせて3種類の手法を紹介しました。それぞれに一長一短があり状況によって使い分けが必要にはなるものの、ボーン検出を使った手法はそれなりに強力なので労力削減に貢献できると思います。

ぜひ使ってみてくださいませ。


記事のヘッダ画像はボーン検出を使った手法による自動検出でin-paintingしたあと、upscaleして合成したものです。upscaleについてはこちらをご覧ください。

できあがり!


この記事が気に入ったらサポートをしてみませんか?