[Amazon Bedrock] Stable Diffusion XLを使用して、我が家のワンコをイラスト化してみました

[Amazon Bedrock] Stable Diffusion XLを使用して、我が家のワンコをイラスト化してみました

Clock Icon2023.10.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

CX 事業本部 delivery部の平内(SIN)です。

Amazon Bedrockを使用することで、生成AIを軽易に利用することが可能です。 今回は、カテゴリ「Image」に分類される、Stability AIStable Diffusion XL(Preview) を使用して、写真を元にしたイラストの作成を試してみました。

2 出力画像

最初に、入力とした画像と、出力を御覧ください。入力画像の構成を活かして、コミック風の画像が生成されていること確認できると思います。

入力画像

出力画像

3 Playgrounds

AWSコンソールで提供されているPlaygroundsでは、軽易にモデルを試すことが出来ますが、設定できるパラメータが制限されるため、できることに限りがあります。

今回試したような、Image to Imageは利用出来ません。

4 boto3

パラメータを自由に設定するためには、API requestで利用する必要がありますが、最新のboto3から、これを利用可能です。

下記が、今回の作業で使用したコードです。

image_2_images.py

import base64
import io
import json
import datetime
import random
import boto3
from PIL import Image


def image_to_base64(image):
    buffer = io.BytesIO()
    image.save(buffer, format="PNG")
    return base64.b64encode(buffer.getvalue()).decode("utf-8")


def base64_to_image(base64_str):
    return Image.open(io.BytesIO(base64.decodebytes(bytes(base64_str, "utf-8"))))


boto3_bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")

model_id = "stability.stable-diffusion-xl"

data_path = "./data"
basename = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")  # 日時文字列をファイル名に使用する

seed = random.randint(0, 1000)
steps = 50
cfg_scale = 30
start_schedule = 0.6
change_prompt = "a dog, light smile,cute,character, room"
negative_prompts = ["", "", ""]
style_preset = "comic-book"
size = 512

input_image = "{}/input.png".format(data_path)
output_image = "{}/{}.png".format(data_path, basename)

# 設定値
config = {
    "filename": basename + ".png",
    "seed": seed,
    "change_prompt": change_prompt,
    "steps": steps,
    "cfg_scale": cfg_scale,
    "start_schedule": start_schedule,
    "style_preset": style_preset,
    "size": size,
    "input_image": input_image,
}

# 入力パラメータ
input_image_b64 = image_to_base64(Image.open(input_image).resize((size, size)))
body = json.dumps(
    {
        "text_prompts": [{"text": config["change_prompt"], "weight": 1.0}],
        "cfg_scale": config["cfg_scale"],
        "seed": config["seed"],
        "start_schedule": config["start_schedule"],
        "steps": config["steps"],
        "style_preset": config["style_preset"],
        "init_image": input_image_b64,
    }
)

# 推論
response = boto3_bedrock.invoke_model(body=body, modelId=model_id)

# 推論結果の画像取得
response_body = json.loads(response.get("body").read())
response_image = base64_to_image(response_body["artifacts"][0].get("base64"))

# レスポンス画像の保存
response_image.save("{}/{}.png".format(data_path, basename))
# 設定値の保存
with open("{}/{}.json".format(data_path, basename), "w") as f:
    json.dump(config, f, ensure_ascii=False)

5 invoke_model()

推論の本体である invoke_model() のリクエストは、下記のようなパラメータで使用されます。

参考 https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/bedrock-runtime/client/invoke_model.html

response = client.invoke_model(
    accept='string',
    body=b'bytes'|file,
    contentType='string',
    modelId='string'
)
name type description default requird
accept string 推論結果のMIMEタイプ application/json
body bytes orfile 推論パラメーター
contentType string 入力データのMIMEタイプ application/json
modelId string モデルの識別子  

レスポンスは、以下です。

{
    'body': StreamingBody(),
    'contentType': 'string'
}

body の中のartifactsで、レスポンス画像を受け取れます。

response_body = json.loads(response.get("body").read())
response_image = base64_to_image(response_body["artifacts"][0].get("base64"))

6 推論パラメータ

invoke_model()のbodyに指定されるパラメータについては、下記にドキュメントがあります。

参考:Inference parameters for foundation models

参考のため、主なパラメータについて、列挙しておきます。

text_prompts: テキストプロンプト weightがマイナスの場合は、ネガティブプロンプトになる

"text_prompts" = [
    {"text": "positive prompt", "weight": 1.0},
    {"text": "negative prompt", "weight": -1.0}
]

cfg_scale: text_promptsで記載した内容にどれだけ従うかを0〜30で指定 大きいほど強く従う)

seed: シード値(0は、ランダム)

steps: 生成ステップ数(大きいほど高精度)※ 50以上で、オンデマンド料金が変わります

style_preset: 画像のスタイル

  • 3d-model
  • analog-film
  • anime
  • cinematic
  • comic-book
  • digital-art
  • enhance
  • fantasy-art
  • isometric
  • line-art
  • low-poly
  • modeling-compound
  • neon-punk
  • origami
  • photographic
  • pixel-art
  • tile-texture

7 同じような画像の生成

コードを実行すると、下記のような「画像ファイル」と「jsonファイル」が出力されます。 入力パラメータのseed値をランダムに指定しているため、毎回、出力画像は変化します。

20231006_073000.png

20231006_073000.json

{
  "filename": "20231006_073000.png",
  "seed": 535,
  "change_prompt": "a dog, light smile,cute,character, room",
  "steps": 50,
  "cfg_scale": 30,
  "start_schedule": 0.6,
  "style_preset": "comic-book",
  "size": 512,
  "model_id": "stability.stable-diffusion-xl",
  "input_image": "./data/input.png"
}

使用されたseed値等のパラメータをjsonファイルに出力しているため、もう一度、同じような画像(完全に固定されていないため、微妙に変わります)を出力することは可能です。

8 最後に

今回は、Stable Diffusion XL(Preview) で写真を元にしたイラストの作成を試してみました。

画像生成AIでは、テキストプロンプトだけで、イメージした出力を得ることは、結構、難しいと思います。そういう意味で、Image to Imageは、画像でテキストプロンプトを補完できるため、うまく使いこなせば、高確率で思った通りの画像が生成ができるようになるのでは?と妄想しています。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.