見出し画像

Stable Diffusionを使ったイラスト作成の記録(2) ~ ネガティブプロンプトと下絵のブレンド ~

前回の記事

シリーズ一覧

Layered Diffusion Pipelineを使うためのリンク集

下絵の変更

前回の生成画像を見て、下絵の女子学生の頭身を改善する方がよいのではないかと思って、下絵とマスク画像を次のように変更しました。左が前回で右が今回になります。

下絵とマスク画像の変更

新しい下絵を使って、前回のスクリプト(2)(通常レイヤーを使った画像生成)を実行してみました。スクリプトはこちら。

# 再掲:スクリプト(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-2)と新しい下絵で生成

頭部が小さくなり、前回と比べて足の方まで描画されやすくなったようです。しかし、まだ身体が横向きになりがちです。

ネガティブプロンプトの活用

前回観察したように、背景レイヤーに女子学生が描かれてしまうのが、構図が崩れる原因の1つと考えられます。これを抑制するために、ネガティブプロンプトを活用してみます。

スクリプトはこちら。スクリプト(1-2)で、背景レイヤーのネガティブプロンプトに"1girl"を入れました。

# スクリプト(2-1)
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",
        ),
        Layer(
            prompt="1girl, solo, high school, school uniform",
            negative_prompt="",
            mask_by="schoolgirl_mask.png",
        ),
    ],
    num_steps=30,
    size=(512, 512),
)

生成された画像はこちら。

スクリプト(2-1)で生成

頭が右上の位置に描画されやすくなり、構図がより安定したようです。

ネガティブプロンプトをさらに強調してみる

ネガティブプロンプトをさらに強調するため、"1girl"を3回繰り返しるバージョンも試してみました。なお、重みを変化させるのは、1単語しかないため効果がありません。スクリプトはこちら。

# スクリプト(2-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 *3",
        ),
        Layer(
            prompt="1girl, solo, high school, school uniform",
            negative_prompt="",
            mask_by="schoolgirl_mask.png",
        ),
    ],
    num_steps=30,
    size=(512, 512),
)

生成された画像はこちら。

スクリプト(2-2)で生成

残念ながら、これははっきりした効果は見られないようでした。今のところは、ネガティブプロンプトの"1girl"を繰り返して強調するメリットはないようです。

画像生成中に下絵とブレンドしてみる

strength値を下げると下絵に近い絵が生成されやすくなりますが、下絵の質が低いので、あまり良い結果にはならなさそうに思います。

そこで、単にstrength値を下げるのではなく、画像生成の中盤まで、生成中の画像を下絵とブレンドすることで、下絵からの乖離を抑えながら画像生成が行えないかと考えました。

レイヤーのmask_byにマスク画像を与える代わりに0~1の間の数字を与えることで、その割合で下絵と生成中の画像を混ぜ合わせることができます。0に近いほど下絵が強く、1に近いほど生成画像に近くなります。

下絵を50%の割合でブレンド

まず、試しに、下絵と生成画像を50%の割合で混ぜるため、mask_byに0.5を与えてみます。

また、いつまでブレンドを行うかについては、全行程の内、最初の50%のパターンと最初の30%のパターンを試してみます。これには同じプロンプトを持つレイヤーを2つ用意して、mask_by=0.5を設定しない方にskip_untilを与えて途中までレイヤーを無視するようにします。

複雑な設定になりましたが、スクリプトは次のようになります。

# スクリプト(2-3)
mask=0.5
skip=0.5
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),
)

スクリプトの冒頭にあるmaskとskipの変数に与える数字を変えることで、マスクの強さとブレンドを行う長さを調整することができます。

最初は、mask=0.5を固定にして、skip=0.5と0.3の2通りを試しました。生成された画像はこちら。

スクリプト(2-3)で、mask=0.5に固定し、skipを変化させて生成

元の構図をかなり尊重した形で画像が生成されました。skip=0.5の方がより下絵に近いですが、塗りが滑らかになり、細部も一部描かれています。

skip=0.3になると、ある程度絵として成立し始めています。校庭がフェンスに変わってしまいましたが、試行回数を増やせばより意図に近いものが出るのではないでしょうか。

しかし、どちらもラフスケッチとしては成立するものの、完成絵としてはクォリティに問題があります。しかし、これらを新たな下絵として、再度image to imageを行って品質を上げていくということも可能ではないかと思いました。

下絵のブレンド率を下げてみる

上では、mask=0.5に固定して比較してみましたが、下絵のブレンド率を下げてみるとどうなるでしょうか。

次は、skip=0.3に固定して、maskを0.5, 0.6, 0.7と変化させ、下絵のブレンド率を下げたものになります。

スクリプト(2-3)で、skip=0.3に固定し、maskを変化させて生成

maskの値が上がる(=下絵のブレンド率が下がる)につれて、下絵から乖離してAIの解釈がより強く入ってきているように思われます。

さらに、mask=0.6に固定して、skip=0.3と0.2に対してもっと多くの画像を生成してみました。

スクリプト(2-3)で、mask=0.6に固定し、skipを変化させて生成

上段がskip=0.3で下段がskip=0.2です。下段の方が書き込みが細かくなっているものの、構図は維持されているように見えます。とはいえ、完成絵としてみると、まだクォリティが十分とはいえないのではないかと思いました。

まとめ

ネガティブプロンプトは一定の効果あり

背景レイヤーでネガティブプロンプトに"1girl"を加えることで、マスク画像の外側に女子学生の頭部が描かれるのを抑制し、構図を維持するのに役立つようです。ただし、"1girl"を繰り返しても効果が強まることはなさそうです。

下絵ブレンドの効果

画像生成プロセスの初期段階で、下絵を生成中画像にブレンドすることは、下絵の構図を生成画像に反映させる点で、大きな効果を持っていると言えると思います。

しかし、構図の維持と引き換えに、画像のクォリティは下絵のラフなスケッチの品質に引っ張られて低下してしまいます。これを解決する方法としては、生成された画像を下絵にして再度image to imageを掛けることが考えられます。

また、maskとskipというパラメータを調整することで、生成画像に対する下絵の影響を制御することもでき、構図を維持しながら生成画像のクォリティを向上するアプローチも考えられます。

Layered Diffusion Pipelineの改善点

下絵ブレンドは有用なユースケースだと考えられるものの、現状の機能では直接サポートされていないため、レイヤーを複雑に組み合わせる必要があります。

mask_byとskip_untilの機能を統合する形でより柔軟かつ直感的なインターフェースを提供できればと思います。

いいなと思ったら応援しよう!