LoginSignup
2
2

More than 1 year has passed since last update.

OpenAIの画像生成APIをFlutterから呼んで画像を生成してみる

Last updated at Posted at 2023-02-09

前提

今回はこちらの記事を参考にさせていただきました!

上記記事ではChatGPTを使用しているのですが、同じAPIを使うのではなく、画像生成APIを使って画像を生成してみます。

環境

  • macOS: 12.6
  • Android Studio Dolphin | 2021.3.1 Patch 1
  • flutter: 3.6.0-0.1.pre
  • Dart: 2.19.0

OpenAIの画像生成APIについて

リクエストの仕方によっていくつか使用方法があります。
今回は文字列を送信して、それを元に生成した画像のURLを返却してもらいます。

以下はリンク先のマニュアルに記載されている、curlでリクエストする方法です。

curl https://api.openai.com/v1/images/generations \
  -H 'Content-Type: application/json' \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "prompt": "a white siamese cat",
    "n": 1,
    "size": "1024x1024"
  }'

$OPENAI_API_KEYが必要となるため取得します。

  1. まずこちらから会員登録してください。メールアドレスの他に、GoogleアカウントまたはMicrosoftアカウントが使用できます。

  2. 右上のアイコンを押してView API Keysメニューを開きます。

  3. Create New Secretボタンを押せばAPIキーを生成することができます。

ちなみにUsageページを見ると無料でAPIを使用できる期間等を見ることができます。使いすぎないようにご注意ください。

手順

Flutterプロジェクトを作成

まずは適当にプロジェクトを作成してください。

pubspec.ymlにdependenciesを追加

今回はdioというパッケージを使用します。HTTP通信を行うために利用します。

pubspec.yml
dependencies:
  flutter:
    sdk: flutter


  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2
  dio: ^4.0.6 # この行を追加

IDEによっては自動でダウンロードしてくれますが、そうでない場合はプロジェクトのルートディレクトリ配下でコマンドを叩いてください。

console
flutter pub get

ファイルを作成

アプリのメインロジック。ただ画像生成ページを呼んでいるだけです。

main.dart
import 'package:flutter/material.dart';
import 'package:open_api/open_api/image_generation_api_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ImageGenerationAPIPage(),
    );
  }
}

画像生成ページです。
ボタンは送信ボタンのようなアイコンを使用してみました。

image_generation_api_page.dart
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';

class ImageGenerationAPIPage extends StatefulWidget {
  const ImageGenerationAPIPage({Key? key}) : super(key: key);

  @override
  _ImageGenerationAPIPageState createState() => _ImageGenerationAPIPageState();
}

class _ImageGenerationAPIPageState extends State<ImageGenerationAPIPage> {
  var imageUrl = '';
  var textForGenerationImageController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Image Generation'),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: Image.network(imageUrl)),
          TextField(
            autofocus: true,
            style: const TextStyle(
              fontSize: 20.0,
              color: Colors.black,
            ),
            controller: textForGenerationImageController,
            decoration: const InputDecoration(
              border: InputBorder.none,
              hintText: 'Type text to generate image!',
            ),
          ),
          IconButton(onPressed: () async {
            String url = await generateImageFromText(textForGenerationImageController.text);
            setState(() {
              imageUrl = url;
            });
          }, icon: const Icon(Icons.send)),
        ],
      ),
    );
  }

  Future<String> generateImageFromText(String text) async {
    String apiKey = 'XXXXXXXXXXXXXXXXXXXX'; // ここをAPIキーに差し替え
    var dio = Dio();
    dio.options.headers = {'Content-Type': 'application/json', 'Authorization': 'Bearer $apiKey'};

    try {
      Response response = await dio.post(
        'https://api.openai.com/v1/images/generations',
        data: {
          'prompt': text,
          'n': 1,
          'size': '1024x1024',
        },
      );
      var generatedImageUrl = response.data['data'][0]['url'];
      print('generatedImageUrl:' + generatedImageUrl);
      return generatedImageUrl;
    } catch (e) {
      print(e);
      return e.toString();
    }
  }
}

レスポンスではAPIが生成した画像へのURLが返却されます。それをsetStateメソッドでStateful Widgetのメンバ変数にセットすることで、画像を表示します。

最初は画像へのURLがないのでエラーになっています。

「a white cat」と入力して送信ボタンを押します。
しばらくすると画像が表示されます。

もう一回押すと違う猫ちゃんが…!!

さいごに

利用すること自体は他の一般的なAPIとあまり変わりはないようです。
ただ生成できるものがすごいので、色々なサービスに組み込んだり、アイディア出しにも使ったりできそうです。
例えばCMでお馴染みの(古い?)「蛍のいる渋谷」を見てみましょう。

人と蛍が共存している感じがありますね…!

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2