🐘

写真から短歌を生成するAIを作ってみた

2024/12/03に公開

はじめに

SREホールディングス株式会社データサイエンティストの恒松です。Python、画像処理を用いた開発をしています。今回は、Image Captioning(画像キャプション生成)を用いて写真から短歌を生成するAIを作ってみました。

生成結果

西荻窪のピンクの象の写真から、「天井から 白き象たち 舞い降りて 軽やかに添う 店の夢模様」という短歌が生成されました。

使用した技術

Image Captioning

Image Captioningは画像から説明文を生成するタスクです。画像に対して説明文を生成することで、画像の内容を理解し、自然言語で表現することができます。今回は、LLavaを用いて画像から説明文を生成しました。LLavaは、画像エンコーダーと大規模言語モデルを組み合わせたマルチモーダルモデルです。

翻訳

LLavaを用いて生成した説明文は英語になっているため、日本語に翻訳しました。翻訳にはGoogle 翻訳とPythonのdeep_translatorというライブラリを使用しました。以下は、翻訳された説明文の例です。

  • 説明文:These are large, white elephant statues or inflatable elephants, which are being used as decorations or promotional items in a shopping mall. They are placed in various locations throughout the mall, and their presence adds a unique and eye-catching element to the environment.
  • 翻訳文:これらは、ショッピングモールの装飾や販促品として使用されている、大きな白い象の像または空気で膨らませる象です。それらはモール内のさまざまな場所に配置されており、その存在は環境にユニークで目を引く要素を追加します。

大規模言語モデルで説明文から短歌を生成する

翻訳された説明文から短歌を生成するために、大規模言語モデルを使用しました。今回は、Open AI APIのgpt-4oを使用しました。プロンプトに「以下の情景から短歌を生成してください。」と入力し、翻訳された説明文を入力しました。

  • プロンプト:以下の情景から短歌を生成してください。
    • これらは、ショッピングモールの装飾や販促品として使用されている、大きな白い象の像または空気で膨らませる象です。それらはモール内のさまざまな場所に配置されており、その存在は環境にユニークで目を引く要素を追加します。
  • 生成された短歌:天井から 白き象たち 舞い降りて 軽やかに添う 店の夢模様

他の大規模言語モデルと比較

比較のために他の大規模言語モデルを使用して、同様に短歌を生成しました。ChatGPTが良さそうだったため、gpt-4oを使用しています。

  • OpenAI ChatGPT:白き象 モールの中に 膨らみて 人の波間に 夢を運びぬ
  • Google Gemini:白き象は 空見上げたり 悠々と モールに立つ 夢を乗せて
  • Anthropic Claude:白き象の 風船ゆらぐ モールの中 買い物客の 目を楽しませて

Web アプリ

生成した短歌をWebアプリで表示しました。Flaskを使用して、画像をアップロードすると、短歌が生成される仕組みです。./templates/以下にアップロード画面のupload.htmlと結果表示画面のresult.htmlを作成しました。

import os
from flask import Flask, redirect, render_template, request, url_for, send_from_directory
from PIL import Image
from image_captioning import generate_description
from generate_tanka import generate_tanka
from translate import translate_description
from dotenv import load_dotenv

# .envファイルから環境変数を読み込む
load_dotenv()

app = Flask(__name__, static_folder="./templates/uploads")
app.config["UPLOAD_FOLDER"] = "./src/templates/uploads/"


@app.route("/")
def index():
    return render_template("upload.html")


@app.route("/upload", methods=["POST"])
def upload_image():
    if "image" not in request.files:
        return redirect(url_for("index"))

    image = request.files["image"]
    if image.filename == "":
        return redirect(url_for("index"))

    image_path = os.path.join(app.config["UPLOAD_FOLDER"], "uploaded.jpg")

    image.save(image_path)

    # 画像をリサイズ
    with Image.open(image_path) as img:
        img.thumbnail((512, 512))
        img.save(image_path)

    description = generate_description(image_path)
    translated_description = translate_description(description)
    tanka = generate_tanka(translated_description)

    return render_template(
        "result.html",
        description=description,
        translated_description=translated_description,
        tanka=tanka,
    )


if __name__ == "__main__":
    if not os.path.exists(app.config["UPLOAD_FOLDER"]):
        os.makedirs(app.config["UPLOAD_FOLDER"])
    host = os.getenv("FLASK_RUN_HOST", "127.0.0.1")
    port = int(os.getenv("FLASK_RUN_PORT", 5000))
    app.run(debug=True, host=host, port=port)

アップロード画面

アップロード画面では、画像をアップロードするフォームを表示します。ファイルを選択してアップロードボタンをクリックすると、画像がアップロードされ、結果表示画面にリダイレクトされます。

<!doctype html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>画像アップロード</title>
</head>

<body>
    <h1>画像をアップロードしてください</h1>
    <form method="post" enctype="multipart/form-data" action="{{ url_for('upload_image') }}">
        <input type="file" name="image">
        <input type="submit" value="アップロード">
    </form>
</body>

</html>

結果表示画面

結果表示画面では、アップロードされた画像、生成された説明文、翻訳された説明文、生成された短歌を表示します。また、戻るリンクを表示して、アップロード画面に戻ることができます。

<!doctype html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>生成結果</title>
</head>

<body>
    <h1>生成結果</h1>
    <p><strong>アップロードされた画像:</strong></p>
    <img src="uploads/uploaded.jpg" alt="Uploaded Image">
    <p><strong>説明文:</strong> {{ description }}</p>
    <p><strong>翻訳された説明文:</strong> {{ translated_description }}</p>
    <p><strong>短歌:</strong> {{ tanka }}</p>
    <a href="{{ url_for('index') }}">戻る</a>
</body>

</html>

発展

写真から短歌を生成する簡単なWebアプリを作成しましたが、以下のように発展させることができると思います。

  1. 技術スタックの拡張:
    • Flaskを使用してWebアプリを作成しましたが、TypeScriptやReactを用いることで、より洗練されたWebアプリを作成できます。
    • boltなどのWebアプリ生成ツールを使用することも出来ると思います。
  2. 百人一首の作成:
    • 浮世絵生成: Sakana AIEVO UKIYOEなどを用いて、百人一首の札に使える浮世絵を生成することができます。
    • 読み上げ音声: VoiceVoxなどを用いて短歌を読み上げる音声合成も行えると思います。

まとめ

写真から短歌を生成するAIを作ってみました。実際に作ってみて、LLavaのImage Captioningの精度の高さと、gpt-4oの短歌生成の品質の高さに驚きました。後から気づきましたが、LLavaはLLMを含んでいるため、今回のようなタスクはLLavaだけでも実現可能だったと思います。今後は、Webアプリ生成や百人一首生成(浮世絵生成、読み上げ音声)などの発展を考えています。

SRE Holdings 株式会社

Discussion