GAS

【GAS】Open AI APIを使って画像生成する方法を完全解説(LINE BOT化も)

thumbnail
n-mukineer
えぬ
えぬ

こんにちは、えぬ(@nmukineer)です!

Open AI APIとGASを使って、日本語から画像を自動生成するスクリプトを書いてみました。生成された画像は、指定したGoogle Driveのフォルダに自動保存されるようにしています。

Open AI APIの設定

Open AIとは、イーロン・マスクらが設立した、アメリカの人工知能(AI:Artificial Intelligence)の非営利研究団体です。

APIを公開しており、アカウント登録をすれば使用することができます(Open AI API)。

ただし、料金は無料ではなく従量制となっていますが、いきなり料金が発生するわけではないので安心して下さい。

2023年1月時点では、登録時に18ドルのクレジットをもらうことができます(3カ月間有効)。

最近ではChatGPT(チャット形式で質問に答えてくれるAI)が非常によくできておりTwitterでざわついたりしていますね。

そんなOpen AIには言葉から画像を生成してくれるDALL-Eというサービスがあります。

このDALL-EのAPIが2022年11月3日に使用可能となり、気軽に外部サービスからもAI画像生成を試すことができるようになりました。

ここからは、Open AIのアカウント登録を済ませサインインまでできている、という前提で話を進めていきます。

API Keyの発行

APIを利用するには、API Keyを発行する必要があります。

個人用設定メニューからAPI設定画面を開く

Open AIのマイページログイン後、右上の「Personal」から、「View API keys」を選択します。(筆者はすでに1つAPI Keyを作成しているのでそのようになっていますが、初回の作成時は異なる表示になっているかもしれません。)

API Keyを発行する

Create new secret key」を選択してAPI Keyを発行します。

API Keyをコピーする

こちらのような画面に発行されたAPI keyが表示されます。赤枠の「コピーボタン」を押してコピーし、メモ帳などに貼り付け保存しておきます(インターネット上には公開しないでください)

このAPI keyは二度と表示されませんので、必ずコピーを完了してからOKボタンを押すようにしてくださいね。

画像生成APIの使い方

画像生成を行うAPIのドキュメントを見ていきます。

curlコマンドの場合、以下のようにすることで画像URLを含むレスポンスを受け取ることができます。YOUR_API_KEYの部分には上で生成したAPI keyを入れるようにしましょう。

curlコマンド

curl https://api.openai.com/v1/images/generations \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -d '{
  "prompt": "A cute baby sea otter",
  "response_format": "b64_json"
}'

レスポンス

{
  "created": 1589478378,
  "data": [
    {
      "url": "https://..."
    },
    {
      "url": "https://..."
    }
  ]
}

リクエストパラメータ

画像生成APIにリクエストする際に必要となるパラメータは主に下記の4つがあります。この4つ以外にもう一つuserというオプションパラメータもあるようですが、ヘビーユースしない限りは必要なさそうですのでここでは割愛します。

パラメータ説明
prompt(必須)画像生成したい言葉を指定します。基本的には英語で指定したほうがよさそうです。“cute cat”
n(任意。デフォルトは1)生成する画像の枚数。2
size(任意。デフォルトは”1024×1024″)出力する画像のサイズ。
“256×256”, “512×512”, “1024×1024”
の3つのうちどれかを指定します。
“512×512”
response_format(任意。デフォルトは”url”)レスポンスフォーマット。
“url”か”b64_json”のどちらかを指定します。画像へのリンクが欲しい場合は”url”, 直接画像データを取得したい場合は”b64_json”を指定するとよさそうです。
“b64_json”
画像生成リクエストパラメータ

GASスクリプト

画像生成を行うOpen AI APIの使い方がわかったところで、GASのコードを書いていきます。

GASのプロジェクト作成方法については以下の記事を参考にしてください。

あわせて読みたい
【無料】GASを使い始めるための3ステップ【簡単】
【無料】GASを使い始めるための3ステップ【簡単】

フローチャート

コードを書く前に、簡単にフローチャートを書いてみます。

画像を自動生成するスクリプトのフローチャート

まず、画像生成APIを使う際に指定する言葉は英語である必要がありますので、日本語を英語に翻訳する必要があります。

その後、翻訳した英語をパラメータとして画像生成APIリクエストを行います。

画像生成結果はurlとしてレスポンスされるので、そのURLから画像をダウンロードします。ダウンロードしたら、Google Driveに保存します。

日本語を英語に翻訳するコード

英語を日本語に翻訳するGASコードは以下の記事で紹介していますので、ご参照いただければ幸いです。今回もそのまま利用します。

あわせて読みたい
GASを使えば1行でGoogle翻訳が可能!
GASを使えば1行でGoogle翻訳が可能!

Open AI 画像生成APIを叩いて画像URLを取得するコード

Open AI画像生成APIを叩いて画像URLを取得するコードはこちらです。

const IMAGE_GENERATION_URL = 'https://api.openai.com/v1/images/generations';
const OPEN_AI_API_KEY = PropertiesService.getScriptProperties().getProperty('OPEN_AI_API_KEY');

function generateImage(text) {
  const options = {
    "method" : "get",
    'contentType': 'application/json',
    "headers": { "Authorization":"Bearer " + OPEN_AI_API_KEY },
    "payload": JSON.stringify({
      prompt: text,
      n: 1,                   //デフォルトと同じであれば省略可
      size: "1024x1024",      //デフォルトと同じであれば省略可
      response_format: "url"  //デフォルトと同じであれば省略可
    })
  }
  const response = UrlFetchApp.fetch(IMAGE_GENERATION_URL, options);
  const imageUrl = JSON.parse(response.getContentText()).data[0].url;

  return imageUrl;
}

GASのスクリプトプロパティにOPEN_AI_API_KEYを登録しておきましょう。スクリプトプロパティの登録方法は以下の記事内で説明しておりますので参考にしていただければ幸いです。

あわせて読みたい
GASからLINE Notifyを使ってLINE通知する方法
GASからLINE Notifyを使ってLINE通知する方法

引数及び戻り値の仕様は以下のようにしました。(レスポンスエラーのハンドリングは省略しています)

  • 引数:生成したい画像を説明するテキスト(型:String)
    • 例:”cute cat”など
  • 戻り値:生成された画像のURL(型:String)

生成された画像URLから画像をダウンロードしてGoogle Driveに保存するコード

以下のスクリプトで画像URLから画像をダウンロードし、Google Driveに保存します。

Google Driveに保存した際に画像の名前を変更しますが、ここではDate.now()を使ってタイムスタンプとしています。

// Open AIサーバーから画像ダウンロードしてGoogle Driveに保存
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
const imageFolder = DriveApp.getFolderById(FOLDER_ID);

function downloadImageFromOpenAiServer(imageUrl) {
  const response = UrlFetchApp.fetch(imageUrl);
  const blob = response.getBlob();  
  let newFile = imageFolder.createFile(blob);
  newFile.setName(Date.now());

  return newFile.getDownloadUrl();
}

ここではスクリプトプロパティにFOLDER_IDを設定しておきましょう。(FOLDER_IDは、Google Driveの任意のフォルダのIDのことです)

ここで作成したメソッドの引数及び戻り値は以下の仕様としました。

  • 引数:画像URL(型:String)
  • 戻り値:Google Driveの画像ダウンロードURL(型:String)

GASコード全体

以上をまとめたGASコードがこちらです。

えぬ
えぬ

今回は生成したい画像の説明文をmain関数の中ベタ打ちしていますが、外部からテキストを受け取ってそれに従って画像生成する、というようなこともできそうです。

const IMAGE_GENERATION_URL = 'https://api.openai.com/v1/images/generations';
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
const OPEN_AI_API_KEY = PropertiesService.getScriptProperties().getProperty('OPEN_AI_API_KEY');
const imageFolder = DriveApp.getFolderById(FOLDER_ID);

// メイン処理
function main() {
  const originalText = 'かわいくない猫';  // ここに生成したい画像を説明する文を書く
  const translatedText = translateJaToEn(originalText);
  console.log(translatedText);
  const url = generateImage(translatedText);
  const driveUrl = downloadImageFromOpenAiServer(url);
  console.log(driveUrl);
}

// 画像生成
function generateImage(text) {
  const options = {
    "method" : "get",
    'contentType': 'application/json',
    "headers": { "Authorization":"Bearer " + OPEN_AI_API_KEY },
    "payload": JSON.stringify({
      prompt: text,
      n: 1,                   //デフォルトと同じであれば省略可
      size: "1024x1024",      //デフォルトと同じであれば省略可
      response_format: "url"  //デフォルトと同じであれば省略可
    })
  }
  const response = UrlFetchApp.fetch(IMAGE_GENERATION_URL, options);
  const imageUrl = JSON.parse(response.getContentText()).data[0].url;
  console.log(imageUrl);
  return imageUrl;
}

// Open AIサーバーから画像ダウンロードしてGoogle Driveに保存
function downloadImageFromOpenAiServer(imageUrl) {
  const response = UrlFetchApp.fetch(imageUrl);
  const blob = response.getBlob();  
  let newFile = imageFolder.createFile(blob);
  newFile.setName(Date.now());
  return newFile.getDownloadUrl();
}

// 英語から日本語に変換
function translateEnToJa(text) {
  return LanguageApp.translate(text, 'en', 'ja');
}

// 日本語から英語に変換
function translateJaToEn(text) {
  return LanguageApp.translate(text, 'ja', 'en');
}

動作確認

上記のGASを実行してみましょう。

画像生成ワード「かわいい猫」:”cute cat”

「かわいい猫」で自動生成された画像

うーん、まあ、かわいいですね…普通な気もするけど。

では、かわいいの逆の言葉でやってみましょう。

画像生成ワード「ブサイクな猫」:”ugly cat”

「ブサイクな猫」で自動生成された画像

確かに…!AIすごい!

猫ばっかりだとアレなので、人物もやってみましょう。

画像生成ワード「筋力トレーニングに励む太り気味のエンジニア」:”An overweight engineer who works hard at strength training”

「筋力トレーニングに励む太り気味のエンジニア」で自動生成された画像

確かに!!!でもなぜアニメ風?笑 あとエンジニア感があまりないような…?(眼鏡か!)

LINE Bot化する

LINE Messaging APIの準備

LINE Messaging APIを使ってLINEのチャンネル作成を行います。方法については以下の記事内に記載してあります。参考にしていただければ幸いです。

あわせて読みたい
【「今日晩御飯どうする?」を解決!】LINE Messaging APIとGASを使って晩御飯候補を決めてもらった
【「今日晩御飯どうする?」を解決!】LINE Messaging APIとGASを使って晩御飯候補を決めてもらった

LINE Bot化したGASスクリプト

LINE Botとして動作するように修正を加えたGASスクリプト全体がこちらです。(不要な関数は削除してあります)

const IMAGE_GENERATION_URL = 'https://api.openai.com/v1/images/generations';
const FOLDER_ID = PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
const OPEN_AI_API_KEY = PropertiesService.getScriptProperties().getProperty('OPEN_AI_API_KEY');
const imageFolder = DriveApp.getFolderById(FOLDER_ID);
const LINE_API_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('LINE_API_ACCESS_TOKEN');
const LINE_REPLY_URL = 'https://api.line.me/v2/bot/message/reply';

// LINEからのWebhookで起動
function doPost(e) {
  const eventData = JSON.parse(e.postData.contents).events[0];
  const replyToken = eventData.replyToken;
  const userMessage = eventData.message.text;
  const messageType = eventData.message.type;
  let replyMessage = "";

  console.log(messageType);
  console.log(userMessage);
  if (messageType == 'text') {
    const translatedText = translateJaToEn(userMessage);
    console.log(translatedText);
    replyMessage = generateImage(translatedText);
  } else {
    replyMessage = "ごめんなさい~そのタイプのメッセージには対応できないんです!「かわいい猫」と打って送信してみてください!";
  }

  replyAsImage(replyToken, replyMessage);
}

// 画像生成
function generateImage(text) {
  const options = {
    "method" : "get",
    'contentType': 'application/json',
    "headers": { "Authorization":"Bearer " + OPEN_AI_API_KEY },
    "payload": JSON.stringify({
      prompt: text,
      n: 1,                   //デフォルトと同じであれば省略可
      size: "512x512",      //デフォルトと同じであれば省略可
      response_format: "url"  //デフォルトと同じであれば省略可
    })
  }
  const response = UrlFetchApp.fetch(IMAGE_GENERATION_URL, options);
  const imageUrl = JSON.parse(response.getContentText()).data[0].url;
  console.log(imageUrl);
  return imageUrl;
}

// 日本語から英語に変換
function translateJaToEn(text) {
  return LanguageApp.translate(text, 'ja', 'en');
}

// LINEに画像メッセージとして返事
function replyAsImage(token, imageUrl) {
  const payload = {
    'replyToken': token,
    'messages': [{
        'type': 'image',
        'originalContentUrl': imageUrl,
        'previewImageUrl': imageUrl
      }]
  };
  const options = {
    'payload' : JSON.stringify(payload),
    'myamethod'  : 'POST',
    'headers' : {"Authorization" : "Bearer " + LINE_API_ACCESS_TOKEN},
    'contentType' : 'application/json'
  };
  UrlFetchApp.fetch(LINE_REPLY_URL, options);
}

動作確認

試しに4つほど生成してみました。結構いい感じの画像が作れているのではないでしょうか?

AIで作成した「寝坊したサッカー選手」
AIで作成した「寝坊したサッカー選手」
AIで作成した「何でも承認してくれる上司」
AIで作成した「何でも承認してくれる上司
AIで作成した「サッカー日本代表」
AIで作成した「サッカー日本代表」
AIで作成した「新幹線で寝過ごした猫」
AIで作成した「新幹線で寝過ごした猫」

余談ですが…「何でも承認してくれる上司」はLINE Bot化してありますのでこちらでもぜひ遊んでみてください(承認欲求が満たされます笑)

あわせて読みたい
上司の承認が遅くてイライラ、を解決!?「何でも承認してくれる上司」で遊んでみた
上司の承認が遅くてイライラ、を解決!?「何でも承認してくれる上司」で遊んでみた

まとめ

今回Open AI APIとGASを使って、日本語から画像を自動生成して保存するスクリプトを書いてみました。

さらに、LINE Bot化してスマホから簡単に試すことができるようにしてみました。

お読みいただきありがとうございました!

このブログを書いている人
えぬ
えぬ
N日後にムキムキになるエンジニア
WebアプリエンジニアとしてIoTシステムを開発中。30代折り返し。 趣味(モノづくり、プログラミング、筋トレ)や子育てのことを主に記事にします。 TOEIC: 900点/第一級陸上無線技術士/第3種電気主任技術者/技術士一次試験合格/基本情報技術者/第2種電気工事士/デジタル技術検定2級(情報・制御)
記事URLをコピーしました