Stable Diffusionを使ったイラスト作成の記録(3) ~ Strengthによる下絵のブレンド ~
前回の記事
シリーズ一覧
Layered Diffusion Pipelineを使うためのリンク集
ライブラリの入手先と使用法(英語) : Githubリポジトリ
日本語での使用方法の解説 : Noteの記事
今回の記事の目的
前回の記事の後半で「画像生成中に下絵とブレンドしてみる」という実験をしてみました。今回の記事では、自作ライブラリ(Layered Diffusion Pipeline)にそのための新機能を追加したので、それを使った画像生成の比較をしてみようという趣旨になります。
Generalized Strength
これまで、入力画像にはstrength、レイヤーにはskip_untilというパラメータで画像生成プロセスに対して与える強度をコントロールしていましたが、これらを統合して、どちらもstrengthでコントロールするようにしました。
さらに、strengthに対してlevelを与えることで、各要素が与える強度をさらに細かくコントロールできるようにしました。従来のstrengthは新しいバージョンではlevel=1.0のstrengthとして解釈されるようになります。
例えば、入力画像に対して、次のように設定することで、画像生成プロセスの進度0.9の段階で入力画像の影響を最大(level=1.0)に、進度0.72の段階で入力画像の影響を中程度(level=0.4)に与えることができます。
initialize=ByImage(
image="schoolgirl.png",
strength=[strg(0.9, level=1.0), strg(0.72, level=0.4)],
),
また、レイヤーに対しては、次のように設定することで、画像生成プロセスの進度0.72の段階でレイヤーの影響を中程度(level=0.6)に与えることができます。
Layer(
prompt="high school, school ground, school building, cherry tree, blue sky",
negative_prompt="1girl",
strength=strg(0.72, level=0.6),
),
今回使用したスクリプト
今回の実験では、前回のスクリプト、入力画像に対してstrengthを適用するスクリプト、レイヤーに対してstrengthを適用するスクリプトの3種類を比較しました。
まずは前回のスクリプトです。ただし、mask=0.6, skip=0.2として実行します。
# 再掲:スクリプト(2-3)
mask=0.6
skip=0.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="1girl",
mask_by=mask,
),
Layer(
prompt=("high school, school ground, school building, cherry tree, "
"blue sky"),
negative_prompt="1girl",
skip_until=skip,
),
Layer(
prompt="1girl, solo, high school, school uniform",
negative_prompt="",
mask_by=ScaledMask("schoolgirl_mask.png", mask),
),
Layer(
prompt="1girl, solo, high school, school uniform",
negative_prompt="",
mask_by="schoolgirl_mask.png",
skip_until=skip,
),
],
num_steps=30,
size=(512, 512),
)
次に、入力画像に対してstrengthを適用するスクリプトです。上のスクリプト(2-3)でのmaskとskipと等価なstrengthとして、strg(0.72, level=0.4)が与えられています。
# スクリプト(3-1)
images = pipe(
initialize=ByImage(
image="schoolgirl.png",
strength=[strg(0.9, level=1.0), strg(0.72, level=0.4)],
),
iterate=[
Layer(
prompt=("high school, school ground, school building, cherry tree, "
"blue sky"),
negative_prompt="1girl",
),
Layer(
prompt="1girl, solo, high school, school uniform",
negative_prompt="",
mask_by="schoolgirl_mask.png",
),
],
num_steps=30,
size=(512, 512),
)
最後に、レイヤーに対してstrengthを適用するスクリプトです。上のスクリプト(2-3)でのmaskとskipと等価なstrengthとして、strg(0.72, level=0.6)が与えられています。
# スクリプト(3-2)
images = pipe(
initialize=ByImage(
image="schoolgirl.png",
strength=0.9,
),
iterate=[
Layer(
prompt=("high school, school ground, school building, cherry tree, "
"blue sky"),
negative_prompt="1girl",
strength=strg(0.72, level=0.6),
),
Layer(
prompt="1girl, solo, high school, school uniform",
negative_prompt="",
mask_by="schoolgirl_mask.png",
strength=strg(0.72, level=0.6),
),
],
num_steps=30,
size=(512, 512),
)
画像生成の結果
同じ乱数シードから生成した画像を横に並べて比較できるようにしました。1列目が前回のスクリプト(2-3)を用いたもの、2列目が入力画像に対してstrengthを適用したスクリプト(3-1)を用いたもの、3列目がレイヤーに対してstrengthを適用したスクリプト(3-2)を用いたものです。
一覧すると、前回のスクリプトの生成画像は、今回の(3-1), (3-2)のスクリプトの生成画像の中間的な画像となっていることが見て取れます。
まとめ
新しく導入したGeneralized Strengthは、「画像生成中に下絵とブレンドしてみる」というアイデアを短いスクリプトで表現することができるようになりました。
2種類のstrength(入力画像に対するものとレイヤーに対するもの)は、少し効果が異なるため、目的に応じた使い分けを考えることができると思います。