見出し画像

漫画を描くことを目的に、ControlNetを上手く使って、絵を描くことなく描きたい絵を出力する

ControlNetの登場以降、画像生成AIを取り巻く状況は大きく変化したと感じています。

画像生成AIにはじめて触れたとき、コンピューターに言葉で指示を与えると画像を出力してくれるという仕組みは技術的に面白いだけでなく、まるでAIが言葉を理解し絵画を創造しているようにも感じられ、とても夢のあるものでした。
ただ、何か少し実用めいたことをさせようとすると、コンピューターに指示を与える方法が言葉しかないのはとても不便でした。

ところが、ControlNetを使えば、言葉での指示に絵や写真を添えることができるようになります。
ControlNetがなかったころは、長大な呪文のようなプロンプトを書いても尚、どんな画像が生成されるかは運次第でした。しかし、いまはControlNetから画像で指示を与えることができるので、プロンプトはずっと短くて済みます。しかも、使えるかどうかわからない画像を大量に出力させてみなくても、少しずつ思った画像に近づけていくことができます。

ControlNetはStable diffusionで使うことができます。ControlNetを使えることが、他の画像生成AIではなくStable diffusionを使う理由にもなっています。


漫画的な何かを作る

前回、ControlNetを上手く使えば、漫画が描けるのではないかなどと安易に書いてしまいましたが、本当にそうなのかというのは気になるところ。

とりあえず今回は、下のような漫画のコマ風の絵を作ってみました。
(なぜ中華風なのかについては、またいずれ機会があれば……)

画像生成AIで作った漫画のコマ風の絵

右の女性、左の男性、背景、それぞれ別々に生成し、ペイントソフトに取り込んで、それぞれ線画・黒ベタの部分と、グレーの部分、白の部分に分離してレイヤー化。グレー部分の濃淡を調整した後、黒線の太さを調整。
効果線やオノマトペ、吹き出しなどを追加して、なんとなくそれっぽい感じにしてみました。
ペイントソフトは、はじめGIMPを使っていましたが、コマの枠線や吹き出しを描くのに便利なメディバンペイント(PC用)を使いました。

先に描きたいものを決める

ただ漫画めいたものを描くだけであれば、Stable diffusionが出力した絵をつなぎ合わせて、お題作文方式でお話を作ることも可能です。
しかし、世の中一般的に「画像生成AIを使って漫画を描く」というと、たぶんそういうことではないと思うのです。

漫画を描く手順としては、まず先に、ある程度ストーリーを考えて、いわゆる「ネーム」を仕上げていく中で、コマ割りや登場人物の配置、台詞の割り振りを決める。その後で、ネームに合うように下書き&ペン入れをするのですよね。
この下書き&ペン入れの部分をうまくAIに描かせるというのが、一般的な「画像生成AIを使って漫画を描く」というイメージだと思います。

なので、この流れをイメージして、一旦、ネームの一コマっぽいものを手書きで描いてみました。(ほかのコマもあるのですが、それについては、またいずれ機会があれば……)
これに沿ってStable diffusionで作り込んでいきます。

ネームの一コマ的なもの

意外に難しいOpenPoseでのポーズ指定

とりあえず右側の人から出力していきます。

右の人

モデルは、CHEYENNE_v16を使っています。

漫画調の線画を出すためにLineAniRedmondV2-Lineart-LineAniAFも使っています。

パラメーターはこんな感じ。

parameters
grayscale, (white background), a middle age woman, full body, domineering, expel, daunting pose, China, period drama, hotel owner, fat woman, <lora:LineAniRedmondV2-Lineart-LineAniAF:1> lineart
Negative prompt: BeyondSDXLv3
Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 7, Seed: 3119755111, Size: 1024x1365, Model hash: 8ea2b6e4e2, Model: CHEYENNE_v16, VAE hash: 235745af8d, VAE: sdxl_vae.safetensors, Clip skip: 2, ControlNet 0: "Module: dw_openpose_full, Model: bdsqlsz_controlllite_xl_dw_openpose [23893c0e], Weight: 1, Resize Mode: Crop and Resize, Low Vram: True, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0, Guidance End: 1, Pixel Perfect: False, Control Mode: Balanced, Hr Option: Both, Save Detected Map: True", ControlNet 1: "Module: depth_midas, Model: bdsqlsz_controlllite_xl_depth [c4d5ca3b], Weight: 0.3, Resize Mode: Crop and Resize, Low Vram: True, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0, Guidance End: 1, Pixel Perfect: False, Control Mode: Balanced, Hr Option: Both, Save Detected Map: True", ControlNet 2: "Module: scribble_hed, Model: bdsqlsz_controlllite_xl_sketch [8e99f467], Weight: 0.7, Resize Mode: Crop and Resize, Low Vram: True, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0, Guidance End: 1, Pixel Perfect: False, Control Mode: Balanced, Hr Option: Both, Save Detected Map: True", Lora hashes: "LineAniRedmondV2-Lineart-LineAniAF: 40b6d27be3a3", TI hashes: "BeyondSDXLv3: 7a11b7b2ad95, BeyondSDXLv3: 7a11b7b2ad95", Version: 1.8.0-RC

プロンプトはそんなに長くないのですが、ControlNetをOpenPoseとDepthとScribbleの3つ重ねてかけたので、パラメーターとしては結構多いですね。

Daz 3Dの素体でポーズを作ってOpenPoseに読み込ませれば、ポーズ指定は簡単だろうと思ったのですが、そこまで簡単にはいきませんでした。

試行錯誤しつつ、ControlNetにDaz 3Dからキャプチャーした下のような画像を重ねて与えて、どうにかなりました。

Daz 3Dの素体の画像

試行錯誤したといっても、せいぜい30枚程度トライしたらこの絵に到達したので、この高々1年程で急速に進化したなあ~という感じです。
まぁ、手の向き変わっとるやんとか、ちゃんと見ると破綻しているところも多いのですが、筆者のような下手くそな人間よりは、パッと見がマシなので十分でしょう。

さて、もっと面倒だったのは左側の男性。

まず、OpenPoseだけでは後ろを向いてくれません。
プロンプトを付け足してどうにか後ろを向かせようとしますが、後ろを向いた瞬間に棒立ち。なぜかポーズの概念がどこかに消えてしまいます。

試行錯誤した結果がこちら。

左の人

parameters
Chinese historical drama, a frightened man, fear, Hanfu, full body, back view, black chinese style boots, cover his hands and face, <lora:LineAniRedmondV2-Lineart-LineAniAF:1> lineart, white background, grayscale
Negative prompt: BeyondSDXLv3
Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 7, Seed: 4007986924, Size: 1024x1365, Model hash: 8ea2b6e4e2, Model: CHEYENNE_v16, VAE hash: 235745af8d, VAE: sdxl_vae.safetensors, Clip skip: 2, ControlNet 0: "Module: scribble_pidinet, Model: bdsqlsz_controlllite_xl_sketch [8e99f467], Weight: 1, Resize Mode: Resize and Fill, Low Vram: True, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0, Guidance End: 1, Pixel Perfect: False, Control Mode: Balanced, Hr Option: Both, Save Detected Map: True", ControlNet 1: "Module: dw_openpose_full, Model: bdsqlsz_controlllite_xl_dw_openpose [23893c0e], Weight: 1, Resize Mode: Resize and Fill, Low Vram: True, Processor Res: 512, Threshold A: 0.5, Threshold B: 0.5, Guidance Start: 0, Guidance End: 1, Pixel Perfect: False, Control Mode: Balanced, Hr Option: Both, Save Detected Map: True", Lora hashes: "LineAniRedmondV2-Lineart-LineAniAF: 40b6d27be3a3", TI hashes: "BeyondSDXLv3: 7a11b7b2ad95, BeyondSDXLv3: 7a11b7b2ad95", Version: 1.8.0-RC

一応、OpenPoseに読ませたDaz 3Dの画像も載せておきます。

Daz 3Dの素体

Scribbleには、一旦Daz 3Dの画像を読ませてプリプロセッサが吐き出した画像を手修正した下記の画像を使用。

ちょっとだけ手修正

元々のモデルのポテンシャルからすると、もっとファインな画像が出るはずなのですが、既に5、60枚程度は出力した後だったので、大丈夫、使える使える。

背景にはTileが活躍

一応、設定的には、古い宿屋で女将さんから門前払いされる男性という設定なのですが、(なんでこんな設定を思いついたかは、またいずれ機会があれば……)ざっくりプロンプトを入れると、こんな画像が出てきました。

最初に出てきた画像

ん~、なんか遠景すぎるんですよね。真ん中の玄関のところだけでいいんだけど……
あと、人の配置を考えると、左右逆の方がありがたいんですよね……

仕方ないので、切り出して拡大するとこんな感じ。

必要なところだけ切り出して左右反転後に拡大

このままでも使えるかなと思ったのですが、エッジが立っていないので、黒を抽出しようとすると、ベターっと真っ黒になってしまって、偽ペン画風の細い線がうまく出ません。
もうちょっと輪郭をはっきりさせたいので、この画像をControlNetのTileに与えて、描き直してみました。

結果はこんな感じ。

ControlNetのTileを使って再描画した画像

parameters
grayscale, China, period drama, evening, Entrance to the old small inn, <lora:LineAniRedmondV2-Lineart-LineAniAF:1> lineart
Negative prompt: BeyondSDXLv3
Steps: 20, Sampler: DPM++ 2M Karras, CFG scale: 7, Seed: 477730040, Size: 1820x1024, Model hash: 8ea2b6e4e2, Model: CHEYENNE_v16, VAE hash: 235745af8d, VAE: sdxl_vae.safetensors, Clip skip: 2, ControlNet 0: "Module: tile_resample, Model: bdsqlsz_controlllite_xl_tile_anime_α [0dbb6686], Weight: 1, Resize Mode: Resize and Fill, Low Vram: True, Processor Res: 512, Threshold A: 1, Threshold B: 0.5, Guidance Start: 0, Guidance End: 1, Pixel Perfect: False, Control Mode: Balanced, Hr Option: Both, Save Detected Map: True", Lora hashes: "LineAniRedmondV2-Lineart-LineAniAF: 40b6d27be3a3", TI hashes: "BeyondSDXLv3: 7a11b7b2ad95, BeyondSDXLv3: 7a11b7b2ad95", Version: 1.8.0-RC

瓦がなんか気持ち悪くなってしまいましたが、そこは切ってしまうので、まあいいでしょう。

あとは素材を切り貼りするだけ……?

こうしてStable diffusionに出力させた画像をそれぞれメディバンペイントに読み込ませます。

どれもはじめにやることは同じで、まずは フィルタ>線画抽出…… から線画&黒ベタの部分を抽出。

別レイヤーでグレーの濃さを編集。白と黒の間にグレーが2段階程度になるように、フィルタ>トーンカーブ…… で適度に調整。

右の女性、左の男性、ともに、背景の上に乗せるので、キャラクターの外側は透明にしなくてはいけません。
手順としては、線画抽出したレイヤのゴミを消して、全面真っ白のレイヤーの上に乗せます。その状態で線画の外側を「自動選択ツール」でクリックすると、キャラクターの外形が選択されるので、全面真っ白のレイヤーに移動して Ctrl+X でキャラクターの外側を一気に消します。

同じ要領でグレーのレイヤーもいらない部分を消します。

メディバンペイントでは、レイヤーにフォルダを作って階層化できるので、キャラごとに個別のフォルダに入れて、白の上に、グレー、線画と重ねて、おきます。

フォルダーを選択しておけば、フォルダーの中のレイヤーを一緒に移動したり拡大・縮小したりできるので、適当に拡大or縮小して、背景の上にキャラを配置します。

上手く配置で来たら、線の太さを調整します。
調整のしかたは、まず、線画のレイヤーで 選択範囲>レイヤーを元に作成/不透明度 を実行すると、黒の線だけが選択されます。次に 選択範囲>選択境界の描画…… を使って線の周囲を太らせたり細らせたりします。

選択範囲の描画

太らせる時は、描画色に黒を選んでおいて、境界線の外側に描画させます。細らせる時は(滅多にないですが)、描画色に透明か白を選んでおいて、境界線の内側に描画させます。

擬音などのオノマトペは、かっこよく描ければ描きたいのですが、ちょっとやそっと練習してもなかなか上手く描けないので手書き風フォントを使っています。
「シュッ!」がふい字P、「わっ!」がしょかきうたげです。

吹き出しも、それっぽく描こうとすると思いのほか難しい。初心者にはなかなかかっこよく描けませんので、メディバンペイントの素材を使っています。ただ、素材のままだと線が細かったので、線の太さは前出の手順で調整しています。

結局、選択したり、消したり、色の濃さを変えたり、ちょっと線を描き足したりはしましたが、絵らしきものは全く描かずにどうにかなりました。

ControlNetとは何か

今回の試行錯誤の中心はControlNetの使い方でした。ここで、ControlNetとは何かを簡単におさらいしておこうと思います。

いま画像生成AIと呼ばれているものは、画像拡散モデル(image diffusion models)あるいは単に拡散モデル(diffusion models)と呼ばれるAIの学習モデルがベースになっています。

少しノイズを加えた画像から元の画像を推測する。これができるのならもう少しノイズを加えた画像からノイズを減らした画像も作れるはず。更にノイズを加えても……と繰り返していくと、完全にノイズだけになった画像からもノイズを取り除く工程を繰り返せば何らかの画像が得られる。つまり、ただのノイズから新たに画像を生成できるというのが拡散モデルの考え方ですよね。

ControlNetは、この繰り返し少しずつノイズを取り除く各工程に対して、別途与えられた画像から抽出した特徴情報を使って、制約を与えてやる仕組みです。

また、text to image(t2i)で使われるプロンプトとなる文字列は、VLM(Visual Language Model)と呼ばれる画像とテキストの関係性を学習したモデルを通して、概念情報に変換されます。そしてこの概念情報が画像の元となるノイズに加えられ、潜在情報となりますが、ControlNetのIP-Adapterでは、ControlNetに与えられた画像を概念情報に変換して、プロンプトから得られた概念情報と同じように潜在情報に加えます。

ControlNetの登場以前には、意図した出力画像を得るためにStable diffusionに画像を与える方法として、image to image(i2i)が使われまていました。i2iは、ただのノイズの代わりに、与えられた画像に適度なノイズを加えて生成画像の起点とし、後は基本的にt2iと同じ工程を踏んでいます。

これに比べると、潜在空間にずっと繰り返し働きかけるControlNetのほうが出力画像をコントロールしやすいというわけですね。

ただ、ControlNetは与えられた画像から特徴情報や概念情報を抽出する際、それぞれ専用にトレーニングされた学習モデルを使います。論文()では小規模なデータセットによるトレーニングでも十分な効果が得られることが示されていますが、これら学習モデルの出来栄えがControlNetの性能を左右していることは間違いありません。
今後、Stable diffusionを使いこなそうとすると、CheckpointやLoRAに加えて、ControlNetのモデルについても気を配っておく必要がありそうです。

Adding Conditional Control to Text-to-Image Diffusion Models


頂いたサポートは今後の記事作成のために活用させて頂きます。