見出し画像

OpenAI APIを使って画像生成してみた


概要

今回は私が行なっているプロジェクトFashion-Folderで画像せいせいAIを使って指定した服を作成するものを作りました!!
意図としては服をアプリに登録する際画像を挿入してもらうのですが一々服の写真を撮って貼り付けるのってめんどくさいですよね
ということでAIに自動で作らせてしまおうという!!ということです。

バックエンド

コードの作成

今回作成したコードがこちらになります!!

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use GuzzleHttp\Client;

class ImageGenerationController extends Controller
{
    public function generateImage(Request $request)
    {
        $client = new Client();
        $apiKey = env('OPENAI_API_KEY');
        
        // フロントエンドから送信されたデータを取得
        $category = $request->input('category');
        $color = $request->input('color');
        $size = $request->input('size');
        $description = $request->input('description', '特にない'); // デフォルトで "特にない" と設定

        // プロンプトをバックエンドで生成
        $prompt = "服の画像を生成して。服のカテゴリーは{$category}で、服の色は{$color}、サイズは{$size}、詳細: {$description}";

        try {
            $response = $client->post('https://api.openai.com/v1/images/generations', [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json',
                ],
                'json' => [
                    'prompt' => $prompt, // 生成したプロンプトを使用
                    'n' => 1,
                    'size' => '512x512',
                ],
            ]);

            $body = json_decode((string)$response->getBody(), true);
            return response()->json(['imageUrl' => $body['data'][0]['url']]);

        } catch (\Exception $e) {
            return response()->json(['error' => 'Failed to generate image: ' . $e->getMessage()], 500);
        }
    }
}

このように意外と意外と短く書けるという事がわかりましたww
まぁAPIにデータを送ってレスポンスを返しているだけなんで当たり前なんですけどねw
それではざっくりコードの説明をしていきたいと思います!!

コード解説

上から順番にこのコードについて解説していきます!!

$client = new Client();
$apiKey = env('OPENAI_API_KEY');

このコードではまずGuzzleのHTTPクライアントインスタンスを作成し、このインスタンスを使ってAPIリクエストを送信します。
次に.env ファイルに保存されているOpenAIのAPIキーを取得します。APIキーはセキュリティのために環境変数で管理しています。

次はOpenAI APIへのリクエスト送信するコードです。

        try {
            $response = $client->post('https://api.openai.com/v1/images/generations', [
                'headers' => [
                    'Authorization' => 'Bearer ' . $apiKey,
                    'Content-Type' => 'application/json',
                ],
                'json' => [
                    'prompt' => $prompt, // 生成したプロンプトを使用
                    'n' => 1,
                    'size' => '512x512',
                ],
            ]);

Guzzleを使ってOpenAIのAPIにPOSTリクエストを送ります。
その引数として大きく分けて三つあります。

  • URL

  • Headers

  • json

URL: OpenAIの画像生成エンドポイント(https://api.openai.com/v1/images/generations)

Headers: Authorization ヘッダーでBearerトークン(APIキー)を送信し、APIに認証します。また、Content-Typeを application/json に指定しています。そうすることによってHTTPリクエストヘッダーの一部で、リクエストのボディがJSON形式で送信されることを示しています。
jsonでAPIに送るデータは以下のようになています

prompt: 生成する画像の詳細情報を記述します。

n: 生成する画像の数(ここでは1枚)。S

size: 生成される画像のサイズ(512x512ピクセル)。

次にAPIから帰ってきたレスポンスボディ(json形式)を文字列として取得し、PHPの配列としてデコードします。

return response()->json(['imageUrl' => $body['data'][0]['url']]);

そして最後に画像のURLを返します。

return response()->json(['imageUrl' => $body['data'][0]['url']]);

レスポンスデータには生成された画像のURLが含まれているため、そのURLをフロントエンドに返します。body['data'][0]['url'] は生成された最初の画像のURLを表しています。

本当の最後にエラーハンドリングですね

} catch (\Exception $e) {
    return response()->json(['error' => 'Failed to generate image: ' . $e->getMessage()], 500);
}

画像生成やAPIへのリクエストが失敗した場合は、例外をキャッチし、エラーメッセージとステータスコード500(Internal Server Error)をフロントエンドに返します。

フロントエンド

コード作成

フロント側のコードがこちらになります。

const handleImageGeneration = async () => {
    setLoading(true); // ロード状態を開始
    try {
        const response = await axios.post('http://localhost:8000/api/generate-image', {
            category: formData.category,
            size: formData.size,
            color: formData.color,
            description: formData.description, // 服の詳細説明をリクエストに追加
        });
        const imageUrl = response.data.imageUrl;
        setFormData((prevFormData) => ({
            ...prevFormData,
            image: imageUrl, // 生成された画像のURLをformDataに保存
        }));
    } catch (error) {
        console.error('画像生成に失敗しました', error);
    } finally {
        setLoading(false); // ロード状態を終了
    }
};

フロント側は主にlaravel側にどんな服を生成して欲しいかのリクエストを送りその後レスポンスを取得するという形になっています。


この記事が気に入ったらサポートをしてみませんか?