謎の発見?Controlnet「スタート0エンド0」で起きた現象 (Pixiv Fanbox)
Content
こんばんは、スタジオ真榊です。今夜はControlnetの実験をしていて偶然発見した生成手法についてご報告です。役に立つものなのかどうなのか、まだよくわかりませんが、とりあえずこういうことが起きたという事象報告としてお読みください。
タイトル画像で紹介したように、「元画像からスタイルを継承しながら線の重ならないガチャができる」という利点があり、さらに背景や表情などをプロンプトで変更しても、大きく構図が変化しないことが確認できました。「よく似ているけど違うイラスト」を作れるこのテクニック。まだ「なんか面白いけど何ができるのかはよくわからない」レベルのものですが、ご興味がある方は試してみて下さい。
実験の発端
さて、Controlnetには、元となる画像から表情や構図、ポーズなどを抽出して、それを継承したイラストを生成する技術が多数盛り込まれています。例えば「Lineart」のプリプロセッサとモデルを使えば、元画像からこのように線画を抽出することができ、同じ線画を継承したイラストを作ることが可能です。
このように、線画だけ継承しつつ、違う塗りになります。こちらは「simple background」を指示しているのであまり振れ幅はありませんが、これを「outdoor」に変えると…
線画の存在しない部分に、その都度違う屋外の背景を描いてもらうことができます。ある意味、「背景部分のジェネレーティブ塗りつぶし」のような効果と言えるかもしれません。
さて、どのイラストもきっちり同じ線画になるのは素晴らしいことなのですが、この構図のまま、もう少しだけ出力結果に「振れ幅」を与えることはできないだろうか?と考えたのが、今回の実験のきっかけです。例えば、Openposeを使えば、このように体の位置を抽出することはできます。(Openpose Faceはイラスト調の顔を認識しづらく、失敗しています)
ただ、これで同じプロンプトのイラストを生成すると…
このように、ポーズが同じではあるのですが、似たイラストを別の線画で描く感じにはならず、Seed値によるランダマイズが掛かってそれぞれ「別の子」というムードになってしまいます。
もちろん、以前紹介したVariation機能を使えば、完成イラストを「少しずらす」こと自体は可能です。
こちらは「バリエーションの強度:0.2」で元画像を生成した例。ところが、さきほどのようにプロンプトを変更して背景を変化させようとすると…
このように、プロンプト変化が構図にも影響して、全く違うイラストになってしまいます。
今回の実験で目指していたのはこちら。
構図やカラーといった全体の要素をしっかり引き継いでいながら、線の重ならない別のイラストにしたいんですね。いまとなってはReferenceOnlyで元画像を読み込ませ、同じプロンプトで生成すれば似たようなことができるのですが、この実験をしていた当時はまだCN1.1が登場したばかりで、Referenceシリーズは存在していなかったのです。そのへんはちょっと我慢していただいて、実験の経緯だけ先にざっとご説明するのでナナメ読みしてください。
最初に考えたのが、「Lineart animeの重み(weight)や掛けるステップ範囲を弱めることで、似ているけど違うイラストを生成できないか?」ということでした。
実験1:Lineartを弱めに掛けてみる
Lineartで元画像から線画を抽出する際、線画がぴったりそのままにならないよう、Controlnetの「重み」を弱めたり、影響がかかるステップ範囲を前半までに留めたりすることで、ちょうどいい振れ幅が出ないか試してみます。
X/Yプロットを使って実験してみたところ…
このように、かなり弱めても元画像そのままの画像が出てしまうことが分かりました。重み0.75、ステップの前半40%に掛けるだけで同じ線画になってしまうのは逆に驚きですね。そこで、もっともっと弱めてみると…
このような結果に。ステップの冒頭20%掛けただけでもう線画がほぼ固定されていることが分かります。Lineart、やはりとんでもないですね。10%にするとほぼControlnetを掛けた意味がなくなり、同じプロンプトでランダム生成しただけというムードになります。
実験2:Scribbleを使ってみる
次に、マウスで雑に描いたポンチ絵でも意図を読み取って美麗なイラストにしてくれる「Scribble」を併用する方法を考えました。まずは、初登場のプリプロセッサ「lineart coarse」を使ってラフ風の線画を抽出します。
「lineart coarse」は、「lineart anime」と違って、線画をある程度強弱をつけながらラフ風に抽出してくれるもの。抽出された画像の右上にある「↓」ボタンをクリックして、この画像をいったん保存し、再度元画像として画面左側で読み込みます。
この作業、実はいちいちダウンロードしなくても、抽出された右側の画像を左側にドラッグするだけでできます。表示された画像をドラッグしたり、右クリック「画像をコピー」で別の入力欄に貼り付けたりするテクニックはとても便利です。
さて、今度はこのラフを、本来は手描きしたラフを読み込ませるためのプリプロセッサ「scribble hed」に掛けてしまいます。
するとこのように、線画がマウスで書きなぐったかのような線に変換されます。これを「scribble」で読み込ませれば…
さきほどの「Controlnet弱める実験」よりも少し振れ幅が出てきました。ただ、やっぱり目鼻口などの位置は一致しすぎていますし、髪の毛やめがねなどの崩壊も気になります。
「だいたいこんな感じでいろいろいい感じにバリエーション描いてよ!」というあいまいな指示をするには、どうしたらいいのでしょうか。例えばこちらの記事で紹介した「Shuffle」を使う方法なども思いつきますが、MultiControlnetを使って複数のControlnet指示を加えないと、なかなかうまくいかなそうです。
【Controlnet1.1検証】新モデル「Shuffle」でイラストを"再構成"しよう!
はいこんばんは、スタジオ真榊です。前回の「Controlnet1.1爆誕!顔抽出&アニメ主線抽出&線画塗りを試してみた」に引き続き、今回もControlonet1.1の検証記事をお届けします。 これから検証するのは、「Shuffle」「Pix2Pix」「Inpaint」の新顔3種モデル。前回紹介した「新Openpose」と「LineartAnime」はControlnet1....
ところが、いろいろ試す中、突然謎の生成結果が出る失敗実験がありました。こちらのXYZプロットをご覧ください。
これは普通に元画像をLineart animeした比較実験なのですが、注目していただきたいのは一番上の段。「Guidance End 0.0」…?
こんな指示をした覚えは…と思い、確かめに行くと…
「0.1」が「0,1」になっとる
入力ミスによって生まれた、「Guidance Startが0.0で、Guidance Endも0.0」という謎の指示。普通に考えれば、それってControlnetをオフにしたのと同じ意味になるのでは?となるわけですが、一段目にはまさに今回の実験で求めていた「全体的な要素をやんわり引き継いだバリエーション」になっているではないですか。
どういうこと?
「Lineart anime」で抽出した画像を「0ステップから0ステップまで掛ける」。こちらの設定で、Seed値ランダムの生成を繰り返してみました。
なぜそうなるのか分かりませんが、線画をほどほどに取り入れながら、プロンプト通りの絵を描いてくれていることが分かります。上段中央のイラストは大きく元画像から離れているのが不可解ですが、おおむね他のイラストは元画像の構図を「参考程度に」取り入れていることが分かります。
念のためもう一回生成してみました。
どれも一切線画は重なりませんが、元画像の要素を弱く引き継いでいます。
全く同じ設定でControlnetをオフにすると…
当然このように、まったく違う構図のイラストが量産されます。髪型や色にも振れ幅があるので、やはり「0ステップ」設定でも、Controlnetによって元の画像の情報が渡されていることは間違いないようです。
X/Y/Zプロットで調べると、どうも第1ステップのみに線画情報が渡されている感じがします。「Guidance Startが0.0で、Guidance Endも0.0」という入力をすると、「0%」の近似値が選ばれ、「第1ステップのみに効かせる」結果になるのかもしれません。
この方法、別のControlnetモデルで行うとどうなるのでしょうか。
Shuffleで「スタート0エンド0」
まずは「Shuffle」から。このような設定で生成してみると…
やはり「オフ」に比べて要素が引き継がれている感じがします。通常の「スタート0エンド1」、つまり全体に掛ける形だとこのようになります。
崩壊してしまうのは、プリプロセッサの方のShuffleが悪さをしているため。画面の大半が黒い色で埋まってしまったせいで、このような画像が生成されています。プロプロセッサ「なし」で再度「スタート0エンド1」を試すと、
このようになります。顔の向きなどは認識していませんが、カラーテイストは継承していますね。では、プリプロセッサ「なし」で問題の「スタート0エンド0」を試すとどうなるか。
Seed値にもよりますが、全体のカラートーンのみを引き継いで、自由にイラストを描いてくれる感じになりました。不思議なのは、全ステップに効果を効かせたさきほどの例よりも、髪の毛などの色合いが元画像に忠実なように見えること。Shuffleの紹介記事のときもこの「光が当たりまくっている感じ」が気になったので、Shuffleを全ステップに効かせるのはやめたほうがいいのかもしれません。
Softedgeで「スタート0エンド0」
今度はCannyやLineart animeよりも柔らかく輪郭を抽出してくれる「Softedge」で試してみます。
面白い!おおむね右向きの構図は引き継がれており、Lineartanimeと似た結果になりました。ちなみに、通常通り全ステップに掛けるとこのようになります。LineartAnimeとほぼ同じですが、色合いに幅がある気がしますね。(首の塗りミスもありますが)
Cannyで「スタート0エンド0」
さて、ここから飛ばし気味で進めます。今度はCanny。
こちらもおおむね似たような結果ですが、9枚に1枚くらいの割合でなぜか2人になったり、大きく構図の異なる別のイラストになったりすることがありました。
depthで「スタート0エンド0」
こちらはほぼ使えない結果となりました。継承できる要素が深度情報なので、きっちり固定しないと意味がありませんから、ほとんどControlnetをオフにしたのと変わらない結果です。同じ理由で、「Openpose」などのモデルもあまり使えないと思われます。
中間考察
ここまでの実験からわかるのは、「スタート0エンド0」を指定すると、エンドは0そのものにはならず、第1ステップのみに効かせた感じの生成結果になるということ。使用したControlnetのモデルにもよりますが、Referenceシリーズのような「線を固定しないスタイル継承」ができそうに見えます。
「reference_adain+attn」を使えば、参照画像の構図なども強力に参照させながら線の重ならないイラストにできるので、さほど需要はなさそうにも思えますが、「第一ステップのみに効かせておおまかな絵の方向性を決める」という骨組みは、別のCNモデルと組み合わせることでなにか応用ができそうです。
Referenceシリーズとの併用
ここまで引っ張ってしまいましたが、Referenceシリーズの登場によって、当初実現したかった「線を固定しないスタイル継承」は既に実用化されています。
ReferenceOnlyを使えば…
このようにやんわりしたスタイル継承ができ、
reference_adain+attnを使えば…
線こそ重ならないものの、構図までより強めに継承させることができます。
これに、それぞれLineartAnimeの「0スタート0エンド」(以下、0→0と表記)をMulti controlnetで混ぜてみることにしました。やり方は簡単で、二つ目のControlnet画面を開いて、同じ画像をLineartAnimeで読み込ませるだけです。X/Y/ZPlotを使って、4種類のseed値で実験しました。
ReferenceOnly実験
左の列が「reference only」のみ、右の列が「reference only + Lineart0→0 」です。忠実度(style fidelity)はデフォルトの0.5です。
右列は水の流れをさらに狭めるイメージというか、ランダマイズの幅が狭まって、より意図したキャラクターの再現ができているように見えます。今度は「reference adain+attn忠実度1.0」に変えて同じことを試します。
adain+attn実験
左の列が「reference adain+attn」のみ、右の列が「reference adain+attn + Lineart0→0 」です。
やっぱり、線は重ならないのに右列の方が整っている感じがします。
Shuffle実験
今度は「Shuffle0→0」との組み合わせ。プリプロセッサは「なし」で読み込ませてみました。
例によって、左列が「reference only」のみ、右の列が「reference only + shuffle0→0 」です。忠実度(style fidelity)はデフォルトの0.5です。
LineartAnimeのときとは違い、ポーズがランダマイズされる効果が出ています。「ポーズがランダムになるが、より元画像に似た感じにできる」を期待していたのですが、特にそんなことはなかった。
こちらは、左の列が「reference adain+attn」のみ、右の列が「reference adain+attn + Shuffle0→0 」。
ここまで来ると微差ですね。reference adain+attnが強力に元画像を継承しているので、さほどshuffle0→0の意味が感じられなかったです。
背景を変えてみる実験
最初のほうに触れた「背景プロンプト変更」をLineartAnime0→0で試してみます。つまり、プロンプト内の (simple white background:1.20)を (outdoor,sky:1.20)に変えて生成するわけですが、普通はプロンプト変更によって構図も大きく変化してしまうはず。LineartAnimeを1ステップ目だけに掛けると…
なんと、成果が出てしまいました。
左列がReferenceOnlyのみ、右列がReferenceOnly+LineartAnime0→0」です。左列では元画像から大きく構図が変化しているのに対し、右列では線を固定しないまでも、おおむね構図が引き継げています。
ちなみに「reference adain+attn」でも同じ設定で試してみましたが、
こちらは元画像の白背景に強く引っ張られてしまって、背景がうまく生成できませんでした。
表情と服装と背景を変えてみる実験
その名の通り、smileをangryに、school uniformをbikiniに、sky,outdoorをbeachに変更してみました。左列がReferenceOnlyのみ、右列がReferenceOnly+LineartAnime0→0」です。
これも、はっきりと右列の方が意図したものが出ています。水着のデザインにセーラー服っぽい残滓が残っているくらいで、右列はおおむね同じキャラクター・構図をやんわりと維持しつつ、プロンプト指示に沿ったものが生成できています。差分…差分に使える気が…する!
まとめ
以上、偶然から生まれたスタート0エンド0テクニックのご紹介でした。いまいち使い途がはっきりしないテクニックではあるのですが、ある画像からスタイル継承したいが、完全に線は重ねたくない(=ガチャしたい)ときに、referenceシリーズと混ぜ合わせて使うのはまずもって有効そうに思えます。また、「スタイル継承をしたいけどプロンプトもいろいろと変えたい」といった場合にも、referenceシリーズだけだと構図まで変化してしまいますが、それを防ぐこともできました。
まだ試せていませんが、同じキャラの別ポーズを生成したいときに、Referenceでキャラを維持しながら、0→0のLineartAnimeなどでおおまかな構図を指示することもできるかもしれません。Control modeを使い分けるとまた何かできるかもしれず、引き続き検証を続けたいと思います。
なにかに使えるようで、超便利というわけでもなさそうな0→0テクニック。なにか面白い使い途を発見された方がいらしたら、ぜひ教えて下さいね。
それでは本日はこのへんで。おやすみなさい!