BedrockにStabilityAIの新たな画像生成モデルが3つ登場しました！

## はじめに
9/5にAmazon BedrockでStability AIの新しい画像生成モデルが３つ発表されましたので早速使ってみました！

https://aws.amazon.com/jp/blogs/aws/stability-ais-best-image-generating-models-now-in-amazon-bedrock/

## ３種の新しい画像生成モデル

新たに発表された３種のモデルの特徴は以下のとおりです。現在はオレゴンリージョンでのみ利用可能でした。

| 特徴 | Stable Image Ultra | Stable Diffusion 3 Large | Stable Image Core |
|------------|-------------------|---------------------------|-------------------|
| パラメータ | 160億 | 80億 | 26億 |
| 入力 | テキスト | テキストまたは画像 | テキスト |
| タイポグラフィ | 大規模表示用に調整 | 大規模表示用に調整 | 異なるサイズやアプリケーションでの汎用性と可読性 |
| 視覚的美学 | 写真のようなリアルな画像出力 | より細かい詳細に注意を払った非常にリアルな出力 | 良好なレンダリング；詳細指向ではない |
|料金(1枚あたり)|0.14ドル|0.08ドル|0.04ドル|

SDXL 1.0の料金が標準品質で0.04ドル、プレミアム品質が0.08ドルであることを考えると、Stable Image CoreがSDXLの標準画質、SD 3 Largeがプレミアム品質に相当し、Stable Image Ultraが更なる上位版という位置付けになりそうですね。

## 早速試してみました

AWSが公開しているブログにサンプルプロンプトが記載されているので、シード値は０で同じプロンプトを使って各モデルによる生成を比べてみました。

### プロンプト

```
photo, realistic, a woman sitting in a field watching a kite fly in the sky, stormy sky, highly detailed, concept art, intricate, professional composition.
```

- Stable Image Core 1.0
![スクリーンショット 2024-09-05 2.39.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/20a519bc-666f-d631-8494-6ed4f190c278.png)

- SD3 Large 1.0
![スクリーンショット 2024-09-05 2.39.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/f8d6b8f8-40a7-0491-9eae-4e7580a46dfc.png)

- SD3 Ultra 1.0
![スクリーンショット 2024-09-05 2.39.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/023e78d4-da58-7bf6-6fae-755502c6a57f.png)

### プロンプト
画像の中に特定の文字列「Stable Image Ultra in Amazon Bedrock」を挿入させることも
```
A stylized picture of a cute old steampunk robot with in its hands a sign written in chalk that says "Stable Image Ultra in Amazon Bedrock".
```

- Stable Image Core 1.0
![スクリーンショット 2024-09-05 2.38.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/53680ca8-db15-020e-628a-049f84a24f1b.png)

- SD3 Large 1.0
![スクリーンショット 2024-09-05 2.37.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/a5e220c4-b751-faf6-ccf2-0c527d6d2231.png)

- SD3 Ultra 1.0
![スクリーンショット 2024-09-05 2.38.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/8df4d3e8-65cd-918c-f5bc-c281f436c6df.png)

それぞれ好みが分かれるところですが、特徴表の通りUltraはよりリアルっぽさがあるように感じられます。恐らく

## ローカルから生成させてみた

事前準備
```sh
pip3 install boto3 streamlit pillow
```



コードを実行すると3種のモデルを選択して画像を生成できるようになるので、日本語で生成したい画像のイメージを入力してください。

また、**Stable Diffusion 3 Largeは画像から画像生成も可能になっているモデルで、"幅が640-1536ピクセル、高さが640-1536ピクセルの画像をアップロードして入力画像として使用することができます。**

```sh
streamlit run app.py
```

※<プロフィール名>には自身の環境に合わせてください。

### オプション
|オプション名|概要|
|---|---|
|aspect_ratio|16:9、1:1(デフォルト)、21:9、2:3、3:2、4:5、5:4、9:16、9:21|
|mode|text-to-image/image-to-image(SD 3 Largeのみ)|
|output_format|出力画像の形式。JPEG、PNG<br>高さ640～1,536ピクセル、幅640～1,536 ピクセル|
|seed|生成の「ランダム性」を導くために使用される0～4294967295の値。<br>指定しない場合、ランダムシードになります。|
|negative_prompt|出力画像に表示したくないキーワード|

```app.py
import base64
import boto3
import json
import os
import streamlit as st
from PIL import Image
import io

CLAUDE_MODEL = "anthropic.claude-3-haiku-20240307-v1:0"

STABILITY_MODELS = {
    "Stable Image Core": "stability.stable-image-core-v1:0",
    "SD3 Large": "stability.sd3-large-v1:0",
    "Stable Image Ultra": "stability.stable-image-ultra-v1:0"
}

session = boto3.Session(profile_name='<プロフィール名>')

bedrock_runtime = session.client("bedrock-runtime", region_name="us-west-2")

st.title("新しいStability AIモデルで画像生成を試そう")

selected_model = st.selectbox("使用するモデルを選択してください:", list(STABILITY_MODELS.keys()))

generation_mode = "text-to-image"
if selected_model == "SD3 Large":
    generation_mode = st.radio("生成モードを選択してください:", ["text-to-image", "image-to-image"])

japanese_prompt = st.text_input("画像生成のための日本語プロンプトを入力してください:")

uploaded_file = None
if generation_mode == "image-to-image":
    uploaded_file = st.file_uploader("元の画像をアップロードしてください", type=["png", "jpg", "jpeg"])

def translate_to_english(japanese_text):
    body = json.dumps({
        "anthropic_version": "bedrock-2023-05-31",
        "max_tokens": 1000,
        "messages": [
            {
                "role": "user",
                "content": f"""あなたは日本語を英語に翻訳し、画像生成に適したプロンプトを作成するエキスパートです。
                以下の日本語テキストを英語に翻訳し、Stable Diffusionのような画像生成AIで使用するのに適したプロンプトに変換してください。
                翻訳されたプロンプトのみを出力してください。

                日本語テキスト: {japanese_text}"""
            }
        ]
    })

    response = bedrock_runtime.invoke_model(modelId=CLAUDE_MODEL, body=body)
    response_body = json.loads(response['body'].read())
    return response_body['content'][0]['text'].strip()

def resize_image(image, max_size=1536):
    width, height = image.size
    if width > max_size or height > max_size:
        ratio = max_size / max(width, height)
        new_size = (int(width * ratio), int(height * ratio))
        return image.resize(new_size, Image.LANCZOS)
    return image

if st.button("画像生成"):
    if japanese_prompt:
        with st.spinner('プロンプトを翻訳中...'):
            english_prompt = translate_to_english(japanese_prompt)
            st.write("翻訳されたプロンプト:", english_prompt)

        with st.spinner('画像を生成中...'):
            try:
                body = {
                    "prompt": english_prompt,
                    "mode": generation_mode
                }

                if generation_mode == "image-to-image":
                    if uploaded_file is not None:
                        image = Image.open(uploaded_file)
                        image = resize_image(image) 
                        buffered = io.BytesIO()
                        image.save(buffered, format="PNG")
                        image_bytes = buffered.getvalue()
                        base64_image = base64.b64encode(image_bytes).decode("utf-8")
                        body["image"] = base64_image
                        body["strength"] = 0.75 
                    else:
                        st.error("画像をアップロードしてください。")
                        st.stop()

                response = bedrock_runtime.invoke_model(
                    modelId=STABILITY_MODELS[selected_model],
                    body=json.dumps(body)
                )
                output_body = json.loads(response["body"].read().decode("utf-8"))
                base64_output_image = output_body["images"][0]
                image_data = base64.b64decode(base64_output_image)

                image = Image.open(io.BytesIO(image_data))

                st.image(image, caption=f"生成された画像 (モデル: {selected_model}, モード: {generation_mode})")

                output_dir = "output"
                if not os.path.exists(output_dir):
                    os.makedirs(output_dir)
                
                i = 1
                while os.path.exists(os.path.join(output_dir, f"img_{i}.png")):
                    i += 1

                image_path = os.path.join(output_dir, f"img_{i}.png")
                image.save(image_path)

                st.success(f"生成された画像が {image_path} に保存されました")

            except Exception as e:
                st.error(f"エラーが発生しました: {str(e)}")
                if 'output_body' in locals():
                    st.write("APIレスポンス全体:", output_body)
    else:
        st.warning("プロンプトを入力してください。")
```

## 実行結果

### テキストから画像生成

![スクリーンショット 2024-09-05 3.31.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/8f9811f7-8a74-542c-77f4-b8a929ebb9a9.png)

### 画像から画像生成
先ほど生成した画像を元に別の画像を生成させてみました。

![スクリーンショット 2024-09-05 3.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354022/62465c10-93b5-c9a8-79df-6855d83cfab3.png)

## ユースケース
ブログでは各モデルのユースケースが記載されていたので、それぞれに適したシーンで是非検証してみたいですね。

| 業界 | Stable Image Ultra | Stable Diffusion 3 Large | Stable Image Core |
|------|---------------------|--------------------------|-------------------|
| 広告とマーケティング | • 高級ブランドの広告<br>• フォトリアリスティックな製品展示 | • 高品質の製品マーケティング画像<br>• 印刷キャンペーン | • ソーシャルメディア広告のビジュアルコンセプトの迅速なA/Bテスト |
| 電子商取引 | • 高級製品のカスタマイズ<br>• オーダーメイド製品 | • 電子商取引サイト全体のほとんどの製品ビジュアル | • 商品画像の迅速な生成<br>• リストの最新状態の維持 |
| メディアとエンターテイメント | • 超リアルなキーアート<br>• マーケティング資料<br>• ゲームビジュアル | • 環境テクスチャ<br>• キャラクターアート<br>• ゲーム内アセット | • 迅速なプロトタイピング<br>• コンセプトアートの探索 |

## 公式ドキュメント
- Stable Image Ultra

https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-diffusion-stable-ultra-text-image-request-response.html

-　Stable Diffusion 3 Large

https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-diffusion-3-large-text-image-request-response.html

- Stable Image Core

https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-diffusion-stable-image-core-text-image-request-response.html