「オリジナルのジェットコースター」の画像をSketch to imageでAI生成してみた

[Supership](https://supership.jp/)の名畑です。[今剣](https://twitter.com/trampshunya/status/1347903977552113665)への想いをありったけ込めて[すえひろがり](https://musical-toukenranbu.jp/pages/suehirogari_ranbuyagaimatsuri)の完走を応援しています。

## はじめに

前回「[「食パンをくわえて走る女子高生」のイラストをSketch to imageでAI生成してみた](https://qiita.com/nabata/items/034766f85499423c9e00)」という記事を書きました。[Stable Diffusion](https://ja.stability.ai/stable-diffusion)の提供元[stability.ai](https://stability.ai/)による画像編集ツール[ClipDrop](https://clipdrop.co/)が提供する**Sketch to image**(**落書きを元にして高品質画像を生成するツール**)のAPIを使ってみたという記事です。

そこでも触れたように、生成された結果に全く納得がいかなかったので、別の挑戦をしてみることにしました。

今回は「**オリジナルのジェットコースター**」のAI生成に挑戦してみます。

「**食パンをくわえて走る女子高生**」を現実に見たことはないですが「**ジェットコースター**」であれば何度も見てきました。つい先日もジェットコースターを見て、それで、生成してみたいなと思いました。


## Sketch to image未使用

まずは前回同様、参考までに、Sketch to imageを使わずに生成してみました。
過去記事「[Stable Diffusionの最新モデル「SDXL 1.0」と過去モデルの生成画像をひたすら比較して進化を実感してみた](https://qiita.com/nabata/items/a9b3e759bc09c20581f6)」のコードを元にしています。[stability.aiのAPI](https://platform.stability.ai/docs/getting-started)を呼び出しています。

```Python
import base64
import os
import requests
import time

engine_id = "stable-diffusion-xl-1024-v1-0"  # SDXL 1.0

api_host = os.getenv('API_HOST', 'https://api.stability.ai')
api_key = os.getenv("STABILITY_API_KEY")

# API Keyの取得確認
if api_key is None:
    raise Exception("Missing Stability API key.")

# API呼び出し
response = requests.post(
    f"{api_host}/v1/generation/{engine_id}/text-to-image",
    headers={
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Authorization": f"Bearer {api_key}"
    },
    json={
        "Samples": 3,
        "text_prompts": [
            {
                "text": "roller coaster"
            }
        ],
    },
)

# レスポンス確認
if response.status_code != 200:
    raise Exception("Non-200 response: " + str(response.text))

# レスポンス取得
data = response.json()

# 画像保存
# ファイル名にはタイムスタンプとengine_id、通番を含めています
# 通番は0〜samplesの値 - 1
for i, image in enumerate(data["artifacts"]):
    with open(f"./{engine_id}_{int(time.time())}_{i}.png", "wb") as f:
        f.write(base64.b64decode(image["base64"]))
```

> roller coaster

というシンプルなプロンプトで生成した結果が下記です。ジェットコースターは和製英語らしい。

![coaster_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/074af6b1-41c2-130f-98df-3f374a74adee.png)

![coaster_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/8bf760d2-53b9-ffdf-5dd7-07f249bc1d01.png)

![no1c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/36e794d6-0492-106b-d8bd-e5e1cda6db68.png)

色々とツッコミどころはあるというか、そもそもまともに動きそうもないですが、まあ、ジェットコースターですね。

## Sketch to imageを使用

はい、ここからが本題です。
**Sketch to image**を使った場合の結果です。
基本のコードは前回の記事「[「食パンをくわえて走る女子高生」のイラストをSketch to imageでAI生成してみた](https://qiita.com/nabata/items/034766f85499423c9e00)」と同様です。

```Python
import requests
import os
import time

r = requests.post('https://clipdrop-api.co/sketch-to-image/v1/sketch-to-image',
                  files={
                      'sketch_file': ('original_image.png', open("./original_image.png", "rb"), 'image/png'),
                  },
                  data={'prompt': 'roller coaster'},
                  headers={'x-api-key': os.getenv("CLIPDROP_API_KEY")}
                  )

if r.ok:
    with open(f"./generated_image_{int(time.time())}.jpg", "wb") as f:
        f.write(r.content)
else:
    r.raise_for_status()
```

### プロンプト

> roller coaster

こちらもシンプルなプロンプトで試してみました。

### 元画像1

はい、ただぐにゃぐにゃの線を描いてみました。

![coaster_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/3af3e0d9-0137-221c-afff-11b42c3e65cf.png)

### 生成画像1

上記の元画像を用いて生成された結果はこちらです。

![coaster_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/459bbc71-d59e-e02a-bf37-acde44d081b1.jpeg)

うーん、あまり線が生かされている感じがない。
流石に無理があったか。

### 元画像2

シンプルにしてみました。

![coaster_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/6142f5ef-6278-1b90-6cef-19c0b1ea7319.png)

### 生成画像2

![coaster_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/6ef1138c-83c5-60dd-90e8-61e3327b3c22.jpeg)

うん、線が生かされている感は出ましたね。

### 元画像3

もう少し複雑な線にしてみました。

![coaster_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/3e98f25c-45f9-1aca-d789-10f15fa151c0.png)

### 生成画像3

![coaster_8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/9ec33b0c-9f0e-b286-72e0-015d4650e328.jpeg)

線は生かされているが、果たしてこれはジェットコースターと呼べるのか。この画像をずっと見ていると背中が汗をかきそう。

### 元画像4

レールを2本の線で描いてみると良くなりそうな気がしたのでこうしてみました。

![coaster_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/320e199a-9551-dd06-b5e5-55e9468132e3.png)

### 生成画像4

![coaster_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/dcaddebb-7db6-de86-9b63-b0b000a47172.jpeg)

かなり近づいた。
もう少し書き込むと、よりイメージ通りになりそうです。

## 最後に

ジェットコースターの画像を日常で必要とすることがないので使い所はなかなか思いつかないですが、こうやって画像の生成をいくつも試していると、いつか役に立つ気はしています。勘違いかもだけれど。

## 宣伝

[SupershipのQiita Organization](https://qiita.com/organizations/supership-inc)を合わせてご覧いただけますと嬉しいです。他のメンバーの記事も多数あります。

Supershipではプロダクト開発やサービス開発に関わる方を絶賛募集しております。
興味がある方は[Supership株式会社 採用サイト](https://supership.jp/recruit/)よりご確認ください。