OpenAIのImages APIを用いた画像生成をPythonで実装してみた記録

[Supership](https://supership.jp/)の名畑です。今更ながら[ヒプノシスマイク](https://hypnosismic.com/)のアニメやCDに触れているのですが、[独歩くん](https://hypnosismic.com/character/shinjuku/doppo/)に共感しながら頑張ります。

## はじめに

[OpenAIのChat API(Chat completions)を用いての会話をPythonで実装してみた記録](https://qiita.com/nabata/items/0919576a926d5bb9814d)では[OpenAI](https://openai.com/)が提供している[Chat API](https://platform.openai.com/docs/api-reference/chat)を用いて会話を実装してみました。

今回は[Images API](https://platform.openai.com/docs/api-reference/images)を使用した画像生成を同じくPythonで実装します。

アカウントの作成やAPI Keyのセットなどについては前の記事をご参照ください。

## Images API

その名前の通り、画像を扱うAPIです。プロンプトか画像を入力すると新しい画像を生成します。
詳しくは[API reference](https://platform.openai.com/docs/api-reference/images)や[Image generationのGuide](https://platform.openai.com/docs/guides/images/image-generation-beta)をご参照ください。

## 価格

価格は[Pricing](https://openai.com/pricing)に書かれていますが、解像度によって変わります。最も安い**256x256**で1imageにつき**0.016ドル**です。1ドル135円換算で**2.43円**です。

| Resolution | Price |
| --- | --- |
| 1024×1024 | $0.020 / image |
| 512×512 | $0.018 / image |
| 256×256 | $0.016 / image |

### Create image

プロンプトを指定すると画像を生成して返してくれます。

- **prompt**
- n
- size
- response_format
- user

**prompt**のみが**required**で、その他は**optional**です。

**n**は画像枚数で**1**がデフォルトで最大値は**10**です。

**size**は**256x256**、**512x512**、**1024x1024**のいずれかが指定できます。デフォルトは**1024x1024**。

**response_format**は生成された画像を**url**で受け取るか、**b64_json**で受け取るか。**URLs will expire after an hour**とあるので、urlの有効期限は1時間です。

**user**はユーザーのモニタリングをするためのものですが、詳しくは[End-user IDs](https://platform.openai.com/docs/guides/safety-best-practices/end-user-ids)をご覧ください。

createメソッドのサンプルコードは下記です。a white laptop、つまり、白いノートパソコンを描くようにプロンプトで指示を出しました。

```Python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
image = openai.Image.create(
  prompt="a white laptop",
  size="256x256"
)
print(image["data"][0]["url"])
```

APIレスポンスは下記の形式です。

```json
{
  "created": 1683178048,
  "data": [
    {
      "url": "https://..."
    }
  ]
}
```

以下の画像が生成されました。

![white_laptop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/6368cf61-c668-681b-b759-3c29e78f6b40.png)

### Create image edit

すでにある画像を元にして編集するためのAPIです。

使えるパラメータは下記の通りです。

- **image**
- mask
- **prompt**
- n
- size
- response_format
- user

太字になっている**image**(元画像)と**prompt**のみがrequiredです。

**mask**は**元画像のうちのどこを編集するか**を指定するパラメータです。元画像の**編集してほしい箇所**を透過させた画像を渡します。

今回は元画像として先ほど作成した画像(white_laptop.png)と、新たにその一部をくり抜いた以下の画像(white_laptop_mask.png)を使ってみます。

![white_laptop_mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/a18f1d38-4a98-de0a-c93c-0d2ca8a42765.png)

コードは下記です。
可愛い妖精(a cute fairy)を描いてもらいます。

```Python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
image = openai.Image.create_edit(
  image=open("white_laptop.png", "rb"),
  mask=open("white_laptop_mask.png", "rb"),
  prompt="a cute fairy",
  size="256x256"
)
print(image["data"][0]["url"])
```

生成された絵は以下です。

![cute_fairy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/ef6b2b8c-de1d-fe21-a56e-e13a681fe853.png)

くり抜いた箇所に妖精が加えられました。

### Create image variation

元画像を与えるとその変化版(variation)を作成してくれるというAPIです。

- **image**
- n
- size
- response_format
- user

**image**(元画像)のみがrequiredです。

先ほどの画像(cute_fairy.png)を元に2枚生成してもらいましょう。

```Python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
images = openai.Image.create_variation(
  image=open("cute_fairy.png", "rb"),
  n=2,
  size="256x256"
)
print(images["data"][0]["url"])
print(images["data"][1]["url"])
```

できた画像は以下の2枚です。

![variation_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/0a29623f-8234-d25d-dfbb-1ca91d8900a2.png)

![variation_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/339eda91-32d6-26ad-53c2-5da4288777bc.png)



## 翻訳

最後に「**入力した指示に応じて画像を生成する**」というコードを書いてみようと思います。

「**日本語より英語の方が結果の質が高い**」という話を聞いたことがあるため、今回は**日本語の入力を英語に翻訳して画像を生成する**ということをやってみようと思います。

コードは前の記事同様で[Examples](https://platform.openai.com/examples)のページの[English to other languages](https://platform.openai.com/examples/default-translate)というサンプルを元にしました。

```Python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")

your_message = input("描いてほしい絵について説明してください: ")

completion = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "system", "content": "You are a helpful assistant that translates Japanese to English."},
    {"role": "user", "content": "Translate the following Japanese text to English:" + your_message}
  ]
)
eng_message = completion["choices"][0]["message"]["content"]
print("英訳されたメッセージ: " + eng_message)
```

試してみたのが下記です。「**白いノートパソコンの上に可愛い妖精がいる**」が私の入力した文章です。

> 描いてほしい絵について説明してください: 白いノートパソコンの上に可愛い妖精がいる
> 英訳されたメッセージ: "A cute fairy is on top of a white laptop."


## 入力した指示に応じて絵を描くコード

```Python
import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")

# 入力
your_message = input("描いてほしい絵について説明してください: ")

# 翻訳
completion = openai.ChatCompletion.create(
  model="gpt-3.5-turbo",
  messages=[
    {"role": "system", "content": "You are a helpful assistant that translates Japanese to English."},
    {"role": "user", "content": "Translate the following Japanese text to English:" + your_message}
  ]
)
eng_message = completion["choices"][0]["message"]["content"]
print("英訳されたメッセージ: " + eng_message)

# 画像生成
image = openai.Image.create(
  prompt=eng_message,
  size="256x256"
)
print(image["data"][0]["url"])
```

「**白いノートパソコンの上に可愛い妖精がいる**」という指示で描かれた絵は以下です。

![fairy_laptop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869934/ad7cb528-6586-334b-6755-d3da42caa514.png)

## 最後に

触っているだけでどんどん時間が溶けていく面白さです。

次回記事では[Stable Diffusion](https://ja.stability.ai/stable-diffusion)を触ってみようと思います。

## 宣伝

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

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