1 はじめに
CX 事業本部 delivery部の平内(SIN)です。
Amazon Bedrockを使用することで、生成AIを軽易に利用することが可能です。 今回は、カテゴリ「Image」に分類される、Stability AI の Stable 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() のリクエストは、下記のようなパラメータで使用されます。
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は、画像でテキストプロンプトを補完できるため、うまく使いこなせば、高確率で思った通りの画像が生成ができるようになるのでは?と妄想しています。