Stable Diffusionを使ったイラスト作成の記録(1) ~ レイヤーを使う ~
はじめに
Layered Diffusion PipelineというStable Diffusionを主にGoogle Colabで使うための自作ライブラリを作ったので、これを使って実際にイラスト作成を行って、ライブラリの改良点を見つけていこうという企画です。
シリーズ一覧
Layered Diffusion Pipelineを使うためのリンク集
ライブラリの入手先と使用法(英語) : Githubリポジトリ
日本語での使用方法の解説 : Noteの記事
下絵
今回は、構図を確定させるために下絵を用意して、それに沿った形でイラストを生成させることを目標にしたいと思います。モデルはイラスト生成に向いているAnything v3.0を使います。
下絵はこれを使います。1分くらいで適当に書きました。学校の校庭に女子学生が1人立ってポーズを取っています。後ろの灰色は校舎のつもりです。
まずはimage to imageで
下絵があるので、image to imageで画像生成させてみます。下絵がかなりラフなので、strengthは強めの0.9で。下がスクリプトになります。
# スクリプト(1-1)
images = pipe(
initialize=ByImage(
image="schoolgirl.png",
strength=0.9,
),
layers=[
Layer(
prompt=("1girl, solo, high school, school uniform, "
"school ground, school building, cherry tree, blue sky"),
negative_prompt="",
),
],
num_steps=30,
size=(512, 512),
)
何回か実行してできた画像がこちら。
女子学生のポーズが下絵通りに生成された画像はありませんでした。他にも、木や空、地面は再現率が高いですが、校舎はありません。
レイヤー機能を使ってみる
女子学生の出現位置を固定化するために、レイヤー機能を使ってみようと思います。レイヤーにマスク画像を付けることで、プロンプトの効果範囲を限定することができるのです。
使うマスク画像はこれです。白いところにプロンプトの効果が限定されます。
スクリプトはこちらになります。
# スクリプト(1-2)
images = pipe(
initialize=ByImage(
image="schoolgirl.png",
strength=0.9,
),
layers=[
Layer(
prompt=("high school, school ground, school building, cherry tree, "
"blue sky"),
negative_prompt="",
),
Layer(
prompt="1girl, solo, high school, school uniform",
negative_prompt="",
mask_by="schoolgirl_mask.png",
),
],
num_steps=30,
size=(512, 512),
)
何回か実行してできた画像がこちら。
女子学生が上手く右側によっている画像もありますが、そうでないものもあります。妖怪が出現してしまったものも1つ。
背景は前のものより意図したものに近づいています。校舎が描かれた画像が生成されるようになりました。
distinctレイヤーを使ってみる
マスク画像の効果をさらに強めるために、レイヤーを通常レイヤーからdistinctレイヤーに変更してみました。スクリプトはこちら。
# スクリプト(1-3)
images = pipe(
initialize=ByImage(
image="schoolgirl.png",
strength=0.9,
),
layers=[
Layer(
prompt=("high school, school ground, school building, cherry tree, "
"blue sky"),
negative_prompt="",
),
Layer(
prompt="1girl, solo, high school, school uniform",
negative_prompt="",
mask_by="schoolgirl_mask.png",
),
],
num_steps=30,
size=(512, 512),
)
distinctレイヤーは、他のレイヤーから独立して画像生成が行われてから他のレイヤーと統合される形で全体の画像が生成されるというプロセスを辿るため、背景と前景の分離がより強くなります。
何回か実行してできた画像がこちら。
しかし、今回はどうやらうまくいかなかったようです。プロンプトで指定していないにも関わらず、背景に女子学生が生成されてしまったのが大きな原因のようです。
そもそもプロンプトに……
そもそも、プロンプトに女子学生(1girl, solo, school uniform)がなくても、女子学生は生成されるのではないか、という疑問がわきました。Anything v3.0は人物イラストにバイアスが掛かっているので、それっぽい部分があればすぐに人物イラストを描いてしまうのではないかと。
なので、最初のスクリプトを変更してこうしてみました。
# スクリプト(1-4)
images = pipe(
initialize=ByImage(
image="schoolgirl.png",
strength=0.9,
),
layers=[
Layer(
prompt=("high school, school ground, school building, cherry tree, "
"blue sky"),
negative_prompt="",
),
],
num_steps=30,
size=(512, 512),
)
何回か実行してできた画像がこちら。
やはり、ばっちり生成されてしまいました。これは下絵に引きずられているということなのでしょう。背景を生成する上では、この効果を抑える手段を取らないといけないかもしれません。
まとめ
下絵について
下絵はある程度、画像生成の指針として機能しているようです。ものによって描画されやすいものとされにくいものがあります。下絵は形の情報よりも色の情報がより影響しているようです。
例えば、女子学生の髪の色は、頭が右上にある時は黒いですが、左下にある時は茶色になり、中央上部では青色になっています。同様のことは服の色にも言えるように思います。
また、左上に頭が出現しないのは、緑髪の女子学生よりも木の葉になる確率がずっと高いためではないでしょうか。また、座った姿勢が多いのは、地面の色が足の色として解釈されているのではないかと思います。
レイヤーについて
前景(女子学生)を別レイヤーに分離するのは画像の質の向上に貢献しそうです。効果は前景と背景の両方に現れています。
背景では、描画内容の指示がより正確に反映されるようになっています。ただし、指定していない女子学生が描画されてしまう問題には別途対処が必要です。
前景では、女子学生の出現位置が意図したものに近づいています。Anything v3.0では、人物を中央に描画したがる傾向があるようなので、マスク画像で位置を限定するのは効果的ではないかと思います。
今後の課題
画像生成プロセスに、物体の形状や、物体の部位ごとの位置を指示する方法を考えることは、今後の課題となります。