見出し画像

Stable Diffusionでプロンプトとシードを画像に出力|Google Colab

Stable Diffusionで出力する画像にプロンプト(呪文)とシード(乱数)も加え、Googleドライブに保存するお話です。環境はGoogle Colabです。

▍ことの背景

ちょっとしたイラストはStable Diffusionでまかなってしまおうと、呪文詠唱を練習中です。

同じ呪文でも画像が異なることも多く、「さっきの画像をベースに調整したい」なんてことがあります。そんなときには、「さっきの画像」と同じシード(乱数)を指定します。呪文と乱数を保存しておけば再現できるわけです。

そんなこんなで、Stable Diffusionで出力する画像に、呪文と乱数も加えました。といっても難しいことはなく、単にmatplotlibで出力しているだけです。Google Colab上で動かし、Googleドライブにファイル出力します。

▍手順

〜パイプラインの準備(公式通り)

ベースはStable Diffusionの公式手順で、「Stable Diffusion Pipeline」セクションの途中でパイプラインをGPUに移動する箇所(以下のコード)までは公式手順と同じです。

pipe = pipe.to("cuda")

Googleドライブをマウント

Googleドライブにファイル出力するため、Googleドライブをマウントし、カレントディレクトリも移動しています。

from google.colab import drive
drive.mount("/content/drive")

# ここではマイドライブ直下の「images」フォルダに移動
path_export = "/content/drive/MyDrive/images"
%cd $path_export

関数を定義

必要となるライブラリをインポートします。

import datetime
import random
import matplotlib.pyplot as plt

関数を定義します。特徴は次のとおりです。

  • 出力する画像の枚数や各パラメータなどは引数で変更できるようにする

  • 呪文の変数promptsはリストで、カンマや改行でつなげて利用する

  • ファイル名は現在日時で出力する

  • 画像のタイトルに乱数を、左上にプロンプトを出力する

def generate_images(prompts, num_images = 1, num_inference_steps = 50, guidance_scale = 8.5, height = 512, width = 512, my_seed = 0):
    for i in range(0, num_images):
        # 乱数を設定(0ならランダム)
        if my_seed != 0:
            seed = my_seed
        else:
            seed = random.randint(1, 9999999999)  # 10桁までのランダムの数値を生成
        generator = torch.Generator("cuda").manual_seed(seed)
        # 画像を生成
        with autocast("cuda"):
            image = pipe(", ".join(prompts), generator=generator, num_inference_steps=num_inference_steps, guidance_scale = guidance_scale, height = height, width = width)["sample"][0]
        # 現在日時を取得
        now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=9))).strftime("%Y%m%d_%H%M%S")
        # 画像を保存
        plt.figure(figsize=(10, 10))  # 出力する画像サイズ
        plt.title(seed, fontweight="bold")  # タイトル(乱数)
        plt.axis("off")  # 軸表示をオフ
        plt.text(0, 0, "\n".join(prompts), verticalalignment="top", bbox={"facecolor": "white", "alpha": 0.5, "edgecolor": "white"})  # 呪文を改行区切りで画像の左上に表示)
        plt.imshow(image)  # 画像を表示
        plt.savefig("{now}.png".format(now=now), bbox_inches="tight", pad_inches=0)  # 余白を削除して日時のファイル名で保存

関数の使い方

呪文はリストにしています。カンマ区切りでつなげることが多いですし、文字列だと画像上に表示した時に横に長くなってしまうので。

# 呪文を指定
prompts = [
    "Concept Art",
    "a smart black cat uses computer on the desk",
    "by Hayao Miyazaki in Studio Ghibli",
    "highly detailed, clear, color",
]

# 10枚生成
generate_images(prompts, 10)
生成された画像例(タイトルは乱数、左上が呪文)
# シードを指定して生成
generate_images(prompts, my_seed=4375281784)

ほかにも、サイズなどのパラメータを変えたければ、引数に指定します。

▍おわりに

PILのImageDrawでもいけそうですが、タイトルらしい表示が欲しかったので、matplotlibで実現しました。

まだまだ上手く呪文を扱えないので、引き続き詠唱の訓練に励みます。呪文のレベルが上がったらまた共有いたしますね〜!

この記事が気に入ったらサポートをしてみませんか?