ノーモア色移り?プロンプトの影響範囲を操作しよう! (Pixiv Fanbox)
Content
こんばんは、スタジオ真榊です。今日はレタッチ機能の掘り下げ記事を更新する予定だったのですが、新たに公開された拡張機能が非常にエキサイティングな内容だったため、順番を差し替えてお送りします!
今回登場したのは、プロンプトの影響を狭めて色移りを起こりにくくしてくれるという拡張機能「sd-webui-cutoff」。
どういう仕組みなのか?どんな効果が得られるのか?色移り防止以外にも応用できるのか?ということで、さっそくあれこれ実験してみたのでご報告したいと思います。
AI術師の悩みの種「色移り」
画像生成AIで複数の色が登場するプロンプトを組むと、よく起きてしまうのが「色移り」です。例えば「black hair」「blue eyes」と指定したとき、黒髪の内側が青く染まる経験をした術師さんは多いのではないでしょうか。
▲「色移り」の例
こうした目から髪への色移りはネガティブプロンプトに「blue hair」を放り込めば避けることができるのですが、「red ribbon」「yellow shirt」「pink skirt」…とさらに色数が増えていくと、配色の正確性はどんどん下がり、生成するたびにピンクの髪になったり青いシャツになったりとさまざまなミスが多発します。こうした現象は「色移り」や「色汚染」などと呼ばれて、特に同一キャラクターの呼び出しを難しくする一因となっていました。
そこで登場したのが、トークンの影響範囲を制限する拡張機能「sd-webui-cutoff」。この機能はプロンプト内の特定のトークンを「ターゲットトークン」として指定することで、その影響範囲を生成者の意図通りにコントロールしよう!という試みです。
先に結果から見ていくことにしましょう。こちらが「a cute girl, orange T-shirt,red ribbon,brown shoes, pink hair, blue eyes, green skirt,yellow sox」というプロンプトで、カラー指定部分をターゲットトークンに指定して生成した結果です。
(※左列が拡張機能オフ、右列がオン)
指定したのは「ピンク髪/青い目/赤リボン/茶色の靴/オレンジTシャツ/緑スカート/黄色ソックス」。「yellow sox」はうまくいきませんでしたが、左列は緑スカートが一つもないのに比べ、右列は髪・シャツ・ズボンの色が全正解。明らかに左列に比べて打率が向上しています。
★2023/3/20注:この実験には賢木が靴下のつづりを「socks」ではなく「sox」と間違えるという致命的欠陥がありました。ちなみに「yellow socks」としても打率は上がらず、danbooruタグに従って「yellow legwear」とするとうまくいきました。
一体どういう仕組み?
公式説明によると、これはいわゆる「75トークンの壁」を利用した拡張機能のようです。トークンの一部を「パディング(余白)トークン」に書き換えたり戻したりして、順繰りにテキストエンコーダに送ることで、生成者の意図していない部分にトークンの効果が生じてしまうのを防ぐ仕組みとのこと。
と、言われてもわかりにくいので公式の図を見てみます。
(https://github.com/hnmr293/sd-webui-cutoff よりスクリーンショット引用▲)
「75トークンの壁」については詳しくは「WebUIの便利機能をマスターしよう!」をお読み頂きたいのですが、Stable diffusionでは75トークンという単位を超えるプロンプトが入力されると、いったんそこで呪文が分割されてしまいます(=75トークンの壁)。その場合、まず75トークンまでの第一呪文グループをCLIPというテキストエンコーダ(トークナイザ)で処理したあとに、新たに76トークン以降の第二呪文グループが送られる…という流れで画像生成が行われます。この「壁」とトークンの余白化を組み合わせて、意図しない範囲にトークン効果が漏れ出すことを防ごう!というのが「sd-webui-cutoff」の仕組みなわけです。
例えば、さきほどの「a cute girl, orange T-shirt,red ribbon,brown shoes, pink hair, blue eyes, green skirt,yellow sox」というプロンプトは、いったん「a cute girl, __
T-shirt,__ ribbon,__ shoes, __ hair, __ eyes, __ skirt,__ sox」とカラー部分が余白にされた状態に書き換えられます。続いて、①「a cute girl, orange T-shirt,__ ribbon,__ shoes, __ hair, __ eyes, __ skirt,__ sox」→②「a cute girl, __
T-shirt, red ribbon,__ shoes, __ hair, __ eyes, __ skirt,__ sox」→③・・・と、ターゲットトークンを一つずつ復活させたプロンプトが、それぞれ別のグループとしてテキストエンコーダに送られます。ベクトル位置についての説明はここでは割愛しますが、ざっくり言ってしまえば食材を全部ごった煮にすると味が混ざるので、食材ごとに下処理を別にしましょうね、というような仕組みと言えばいいでしょうか。
能書きはこれくらいにして、さっそく導入方法や使い方を見ていきましょう。
▽導入方法
導入方法は簡単で、拡張機能タブから「https://github.com/hnmr293/sd-webui-cutoff」を「URLからインストール」の欄に放り込んで「インストール」すればOK。
「適用してUIを再起動」すると、t2i画面の下部(controlnetなどが表示されるところ)に「Cutoff」というプルダウンメニューが追加されます。
使い方
・「Enable」をONにすれば動作する。「Target tokens (comma separated)」に、指定したいターゲットトークンを入力。複数指定したい場合は上の図のようにカンマ「,」で隔てればOK。
・「weight」で影響度の強さを選べる。デフォルトは0.5で、最大2。さきほどの実験では最大の「2」にした。1.5以下だと色分けの正解率が思わしくなかったため。
・「Detail」タブを開くと「cutoff strongly」という機能が出てくる。公式によると、特定のトークンを指定して、後続のプロンプトの影響を受けるか、受けないかを決められる設定とのこと。例えば「a cute girl」と入れて「cutoff strongly」をenableにすると、「a cute girl, __ T-shirt,__ ribbon,__ shoes, __ hair, __ eyes, __ skirt,__ sox」というプロンプトが生成される。逆にオフにすると、通常通りの「a cute girl, orange T-shirt,red ribbon,brown shoes, pink hair, blue eyes, green skirt,yellow sox」が代わりに送られる。
色移り防止以外の応用法は?
プロンプトの意図しない動作を防ぐ方法は、これまでにもいくつも考案されてきました。Latent Couple extensionはキャンバスを複数の部位に切り分けて、それぞれに意図したプロンプトを影響させようというアイデアですし、プロンプトが区切られる場所を強制できる「BREAK」(WebUIの便利機能をマスターしよう!参照)も、テキストエンコーダの限界による「75トークンの壁」を利用して、より意図に近い生成結果に導こうというものでした。
それでも、100%はありえないのがAIイラスト。Controlnetなどさまざまな「交渉方法」が出来て、人間はよりSDと仲良くなれてきたわけですが、cufoffの登場によってさらにプロンプトの確実性を上げられるでしょうか。まずは多数の色分けを打率よく指示できることがわかったので、色彩以外の要素指定についてもこの機能が活用できるかどうか、今度は2人組の被写体でいろいろ実験してみました。
「短い黒髪 & 長い銀髪」
まずはスタンダードに、短髪と長髪の女の子をモデルに生成実験を行います。
プロンプトは「2girls A and B,A girl have short black hair,B girl have long silver hair」。ターゲットトークンは「short,black,long,silver」。
「やや、効いた…かな?」レベルですね。上から二段目はほとんど左右が同じ構図なので、効いている感を感じられます。ただ、はっきりとした有意差があるとまでは言えないかな。
次はもう少し違いが分かりやすいように、お題の難易度を上げてみましょう。
黒ボブカットオレンジ瞳 & 銀ポニテ青瞳
プロンプト:2girls A and B,A girl have black bob hair and orange eyes,B girl have silver ponytail hair and blue eyes
ターゲットトークン:black bob,orange,silver ponytail,blue
ターゲットトークンをどこで「,」で区切ったらいいか少し悩んだのですが、とりあえずこれでやってみます。
※ここから長く失敗が続きます。興味のない方は「これが成功したプロンプトだ!」まで飛んで下さい。
うまくいったのは一番下くらいで、全体的に効果が今ひとつですね。むしろ、右列のほうが黒髪が出なかったケースがあり、有意差が見られません。
そこで、今度はターゲットトークンの区切りを変えて、単語を全部カンマで区切ってみます。
プロンプト:2girls A and B,A girl have black bob hair and orange eyes,B girl have silver ponytail hair and blue eyes
ターゲットトークン:black,bob,orange,silver,ponytail,blue
今度もうまくいかず。次はプロンプトを見直してみます。先程は「and」を使っていたのですが、今度は単純にカンマで区切ってみることに。
プロンプト:2girls A and B,A girl have black hair, bob cut,orange eyes,B girl have silver hair,ponytail,blue eyes
ターゲットトークン:black,bob cut,orange,silver,ponytail,blue
やはりうまく行きません!髪色と瞳の色のセットはいずれも打率がほとんど変わらず、髪型が誤って入れ替わっているケースも左右とも確認されます。
今度は純粋に色のみをターゲットにしてみます。
プロンプト:2girls A and B,A girl have black hair, bob cut,orange eyes,B girl have silver hair,ponytail,blue eyes
ターゲットトークン:black,orange,silver,blue
やはり有意差は見られず、というより左列がもともと結構打率が良いので、拡張機能を使っている効果が感じられない結果に終わりました。次はBREAK構文を使って文章の前後を断ってみます。
プロンプト:2girls A and B,A girl have black hair, bob cut,orange eyes,BREAK B girl have silver hair,ponytail,blue eyes
ターゲットトークン:black,orange,silver,blue
うーん…
という感じでしばらく試行錯誤が続きました。ターゲットトークンがいったん空欄になることをもう一度思い出して、プロンプトとターゲットトークンがどういう組み合わせになればAIにとって間違えにくくなるかを考えてみます。
これが成功したプロンプトだ!
プロンプト:2girls A and B,A girl have black bob cut and orange eyes, B girl have silver ponytail and blue eyes
ターゲットトークン:black bob cut,orange eyes,silver ponytail,blue eyes
結論から言うと、「掟破りのターゲット全部入れ」が実は正解でした。こうすることによって、
①2girls A and B,A girl have black bob cut and _____, B girl have _____ and _____
②2girls A and B,A girl have_____ and orange eyes, B girl have _____and _____
③2girls A and B,A girl have_____ and _____, B girl have silver ponytail and _____
④2girls A and B,A girl have _____ and _____, B girl have _____and blue eyes
このような呪文グループに分割されてそれぞれCLIPに送られるので、最も混線が減るのではないか?と予想したわけです。
その結果…
最後の1枚だけ黒髪が出ませんでしたが、似たり寄ったりだったさきほどまでの実験に比べ、明らかに右列の打率が上昇したことが体感できました!
もしかするとたまたまかもしれないので、何度か同じ条件でSeed値だけランダム生成してみると…
こちらも失敗はあるものの、二枚目・四枚目で左列のミスが右列で修正されています。
これは右列2、3,4,5枚目がほぼ狙い通りに!左列はひとつも成功した組み合わせがないので、拡張機能の威力が分かります。パーフェクトな内容ではないものの、さほど操作は難しくないので、十分有用な打率アップ機能と言えるのではないでしょうか?
最後に、髪型や目の色に表情もプラスした高難易度のプロンプトを試してみます。
『最終実験】口を開けて怒る黒ボブカットオレンジ瞳 & 目を閉じて笑う銀ポニテ青瞳
プロンプト:2girls A and B,A girl have black bob cut and orange eyes, openmouth angry, B girl have silver ponytail and blue eyes,closed eyes smile,
ターゲット:black bob cut,orange eyes,openmouth angry,silver ponytail,blue eyes,closed eyes smile
今回もターゲット全部盛りメソッドです。これはかなり難しそう…。
左列は一人も目を閉じていないのに対し、右列は「銀髪の子が目を閉じている」は100%の達成率となりました。ただ、怒り顔はあまり出ませんでしたし、髪型のヒット率は下がっているように感じるので、まだまだ研究が必要そうです。もちろんざっくりした打率は左に比べてはるかに高いのですが、完璧とはいえない結果でしたね。
ちなみに、怒り顔を強調して(angry:1.4)とし、ターゲットにも(angry:1.4)を入れてみたところ、それ以降cutoff:enable時の作画がおかしくなるのを確認しました。もしかすると強調構文は何かエラーを引き起こすのかもしれません。似た現象が起きた方がいらっしゃいましたら、コメント等で教えて下さいね。
そんなわけで、ずいぶん長くなってしまいましたが、今夜は「ノーモア色移り?プロンプトの影響範囲を操作しよう!」でした。次の更新は明日か明後日、「レタッチ(inpaint)機能が理解る!修正&入れ替え徹底解説」をお届けできると思います。今夜もまた、新たなゲームチェンジを目の当たりにしてしまった…
それでは皆様、素晴らしき色分けライフを!スタジオ真榊でした。