【コピペOK】無料で自作!LINEで送った画像を英語↔︎日本語にOCR翻訳【GAS】

Google Apps Script

コピペ用ソースコード内で呼び出す関数が間違っているとご指摘いただきました。

以下修正しました。ご指摘ありがとうございました!

修正前:var translatedText = googleTranslate(ocrText);

修正後: var translatedText = deeplTranslate(ocrText);

今回は、OCR機能を利用して画像のテキスト内容を翻訳する機能を検証しましたので手順を紹介します。

LINEで翻訳してほしい画像を送ると、日本語のテキストは英語に、英語のテキストは日本語にしてくれます。

手書きもしっかり翻訳してくれます。

下手くそなミュウの絵はちゃんと無視してくれました

LINEとGASの連携

LINEとGASを連携させます。詳しい手順については以下の記事をご参照ください。「家計簿botを作る」とありますが、連携の手順については全く同じように進めていただければOKです!

Google Driveの設定

LINEで送った画像を一時的にGoogle Driveに保存するため、保存用のフォルダを作成しておきます。

設定方法については以下記事の「Google Driveの設定」をご参照ください。

作成したフォルダのIDはGASのスクリプトに記載するため控えておいてくださいね!

DeepLのアカウント登録

DeepL APIを使用するにはアカウント登録が必要です。

まず、DeepL APIのページを開き、「無料で体験する」を押します。

無料版は500,000文字/月まで翻訳できます。

メールアドレスとパスワードを入力し、住所氏名など必要事項を入力のうえ登録します。

複数アカウント作成防止のため、クレジットカードの登録が必須となっています。

(登録しても自動で課金されることはありません)

アカウントが作成できたら、マイページの「アカウント」タブからAPIキーを取得します。画面下のほうに「DeepL APIで使用する認証キー」というものが表示されていますので、こちらをコピーしておきます(後ほどGASのスクリプトに記載します)。

gasに記載する際には、

const TOKEN = "DeepL-Auth-Key  XXXXXXXXXXXXXXXXXX"

のように、「DeepL-Auth-Key + スペース + トークン」 を設定するようにしてください。「DeepL-Auth-Key」がないと失敗します。

参考:Translate Text(DeepL 公式ドキュメント)

GASのスクリプトを作成する

GASのスクリプトを作成していきます。

Google Apps ScriptでDrive APIを有効にする

まず、GAS上でDrive APIを有効化しておきます。これを忘れるとGoogle Driveへのファイル操作ができませんので注意してください。こちらも詳細は以前の記事にて紹介しています。

DeepLで翻訳する処理の実装

以下がdeepl翻訳用の関数になります。

// Deepl翻訳
function deeplTranslate(ocrText){

  const deeplUrl = "https://api-free.deepl.com/v2/translate";
  var deeplOptions = createOptions(ocrText, "JA");
  
  var deeplResult = UrlFetchApp.fetch(deeplUrl, deeplOptions).getContentText();
  var json = JSON.parse(deeplResult);

  // 翻訳対象のテキストが日本語の場合英語に翻訳
  if (json["translations"][0]["detected_source_language"] == "JA"){
    deeplOptions = createOptions(ocrText, "EN");
    deeplResult = UrlFetchApp.fetch(deeplUrl, deeplOptions).getContentText();
    json = JSON.parse(deeplResult);
  }
  var res = json["translations"][0]["text"];
  res = res.trimStart();

  return res;
}

引数ocrTextには、gasのDrive.Files.insertで画像からテキストを抽出した内容が入っています。

画像60行目のCreateOptions関数はUrlFetchApp.fetchでDeeplにアクセスする際の引数を作成しているメソッドです。引数の”JA”は、翻訳対象のテキストの言語を指定します。CreateOptions関数は以下になります。

// create options
function createOptions(ocrText, lang){

  var deeplOptions;
  const deeplToken = DEEPL_TOKEN;

  var header = {
    'Authorization': deeplToken
  };
  var payload = {
    'text': ocrText,
    "target_lang" : lang
  };
  var deeplOptions = {
     'headers' : header,
     'payload' : payload
  };
  return deeplOptions;
}

62行目でDeeplのAPIにリクエストを送り、getContentTextでテキストとして取得します。

DeepL APIからのレスポンスは以下のような内容となっています。

{
  "translations": [
    {
      "detected_source_language": "EN",
      "text": "これはLINEから送られた画像のテキストです。"
    }
  ]
}

APIからのレスポンスはJSON型(JavaScript Object Notation)という形式になっており、このままだと扱えないのでGASで扱える形に8行目のJSON.parseにて変換しています。

11行目では、翻訳対象の画像のテキストが日本語(JA)の場合の処理になります。戻り値にある「detected_source_language」の中身が日本語の場合は、英語で翻訳させるため再度APIにリクエストを投げます。

71行目の json[“translations”][0][“text”]で翻訳された文章を取り出し、1行目に改行が入っているのでそれを除去してLINEに応答メッセージとして返します。

ちなみにGoogle翻訳を使うときはどう書くの?

Google翻訳を使う場合はgasのLanguageApp.translateを使います。

// result: これはペンです。
result = LanguageApp.translate("This is a pen.", "en",  "ja");

translate(text, sourceLanguage, targetLanguage ) となりますが、 sourceLanguageを省略すると言語が自動検出されます。

Google翻訳とDeepL翻訳の比較

Google翻訳とDeepL翻訳の翻訳結果を比較してみます。

翻訳させる文章は以下にします。

Google has been under pressure since late last year, when Microsoft-backed OpenAI unveiled new ChatGPT software. It quickly became a viral hit for its facility in passing business school exams, composing song lyrics and answering other questions.

Microsoft this week said a new version of its Bing search engine, which has lagged Google for years, would use the ChatGPT technology in an even more advanced form.

Though investors have embraced the push for artificial intelligence, sceptics have warned rushing out the technology raises risks of errors or otherwise skewed results, as well as issues of plagiarism.

A Google spokesperson said the error highlighted “the importance of a rigorous testing process, something that we’re kicking off this week with our Trusted Tester programme”.

“We’ll combine external feedback with our own internal testing to make sure Bard’s responses meet a high bar for quality, safety and roundedness in real-world information,” they said.

Google’s Bard AI bot mistake wipes $100bn off shares

左がGoogle翻訳、右がDeepL翻訳の結果です。

左:Google翻訳 / 右:DeepL翻訳

ぱっと見、DeepL翻訳のほうが自然な文章になっていますね。しかし、文章の後半で「だけでなく、盗作の問題.」と訳されており、Google翻訳では「盗作の問題が生じると警告している」ときちんと翻訳できているのに対し、意味の通る内容になっていない箇所がありました。

また、DeepLでは「マイクロソフト」「グーグル」など、一部の固有名詞が片仮名に変換されていたり、一部は英語のままだったりとバラつきがありました。

もっといろんなパターンで試してみると差が出てくるかもしれませんが、どちらを使うかは好みで良いんじゃないかと思います。

コピペ用ソースコードはこちら

以下、LINEで画像を送ると翻訳して返すソースコードです。「XXXXXXXXXXXXXXXXXXXX」の部分はご自身の環境に合わせて変更してください。

なお、GASのOCR処理についての解説は過去記事にて詳しく解説しています。

const ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXXXXX';
const LINE_ENDPOINT = "https://api.line.me/v2/bot/message/reply";
const LINE_DATA_ENDPOINT = "https://api-data.line.me/v2/bot/message/";
const FOLDER_ID = "XXXXXXXXXXXXXXXXXXXX";
const DEEPL_TOKEN = "XXXXXXXXXXXXXXXXXXXX";

function doPost(e) {

  // LINEからPOSTされるJSON形式のデータをGASで扱える形式(JSオブジェクト)に変換
  var json = JSON.parse(e.postData.contents);

  // LINEから送信されたレシート画像を取得
  var img_url = LINE_DATA_ENDPOINT + json.events[0].message.id + "/content";
  var img_options = { "headers" : { 'Authorization': 'Bearer ' + ACCESS_TOKEN } };
  const blob = UrlFetchApp.fetch(img_url, img_options).getBlob();   // blob型で画像を取得

  // Google Driveに取得した画像をアップロード、OCRを同時実行してGoogleドキュメント形式で保存
  var driveOptions = {
      "title": "test.jpg",
      "parents": [{id: FOLDER_ID}] 
     };
  const image = Drive.Files.insert(driveOptions, blob, { "ocr": true });  // ocrLanguage省略で自動検出
  var ocrText = DocumentApp.openById(image.id).getBody().getText();    // ドキュメント内のテキストを取得

  // Deeplで翻訳
  var translatedText = deeplTranslate(ocrText);

  // 読み取り後は指定したフォルダ内のファイルすべて削除
  var folder = DriveApp.getFolderById(FOLDER_ID);
  var files = folder.getFiles();
  while(files.hasNext()){
    var file = files.next();
    file.setTrashed(true);  
  }

  // 応答用のメッセージを作成
  var message = {
                  "replyToken"  : json.events[0].replyToken,
                  "messages"    : [{"type": "text",         // メッセージのタイプ(画像、テキストなど)
                                    "text" : translatedText}] // メッセージの内容
                };
  // LINE側へデータを返す際に必要となる情報
  var options = {
    "method" : "post",
    "headers" : {
      "Content-Type" : "application/json; charset=UTF-8",  // JSON形式を指定、LINEの文字コードはUTF-8
      "Authorization" : "Bearer " + ACCESS_TOKEN           // 認証タイプはBearer(トークン利用)、アクセストークン
    },
    "payload" : JSON.stringify(message)                    // 応答文のメッセージをJSON形式に変換する
  };
  // LINEへ応答メッセージを返す
  UrlFetchApp.fetch(LINE_ENDPOINT, options);
}

// Deepl翻訳
function deeplTranslate(ocrText){

  const deeplUrl = "https://api-free.deepl.com/v2/translate";
  var deeplOptions = createOptions(ocrText, "JA");
  
  var deeplResult = UrlFetchApp.fetch(deeplUrl, deeplOptions).getContentText();
  var json = JSON.parse(deeplResult);

  // 翻訳対象のテキストが日本語の場合英語に翻訳
  if (json["translations"][0]["detected_source_language"] == "JA"){
    deeplOptions = createOptions(ocrText, "EN");
    deeplResult = UrlFetchApp.fetch(deeplUrl, deeplOptions).getContentText();
    json = JSON.parse(deeplResult);
  }
  var res = json["translations"][0]["text"];
  res = res.trimStart();

  return res;
}

// create options
function createOptions(ocrText, lang){

  var deeplOptions;
  const deeplToken = DEEPL_TOKEN;

  var header = {
    'Authorization': deeplToken
  };
  var payload = {
    'text': ocrText,
    "target_lang" : lang
  };
  var deeplOptions = {
     'headers' : header,
     'payload' : payload
  };
  return deeplOptions;
}

DeepL APIの使用状況を確認する方法

DeepL APIの利用状況は、マイページのご利用状況タブから確認できます。

昨日登録して、この記事を書くのに色々と検証したので1日でけっこう利用量が増えていました。でも、普通に使うぶんには500,000文字/月で問題ないかと思います。

まとめ

今回は、Google Apps Script(GAS)とLINEを連携させて、LINEで送った画像の文字を日本語/英語にDeepL翻訳する方法をご紹介しました。

DeepLのAPIは無料で使うことができ、精度の高い翻訳ができます。

今回はLINEと連携しましたが他にもChatwork、Slackなどのコミュニケーションツールや、freeeなどの会計ソフトといった外部アプリケーションとの連携ができますので、幅広い分野で業務効率化に生かせそうです。

▼ DeepL単体でOCR機能を使用する方法は以下にて解説しています

▼ GASとLINEの連携方法(LINE家計簿botを作る手順)

デスクの脚につけて邪魔にならないサイズ感。マットな質感とお洒落なカラーがかっこいい。マグネットタイプで着脱も楽です。
¥1,690 (2023/10/26 16:50時点 | Amazon調べ)

コメント

  1. gamu より:

    参考にしましたありがとうございます。
    コピペ用ソースコードのところ、

    // Deeplで翻訳
    var translatedText = googleTranslate(ocrText);

    になってるので、deeplTranslate にしたらエラー無くなりました。

    • chaso chaso より:

      ご連絡ありがとうございます!
      ご指摘もありがとうございます。大変助かりました♪
      記事直しておきます。

  2. ぶんぶく茶釜 より:

    コピペ用ソースコードをGASに貼り付けて、GASで実行したところ
    TypeError: Cannot read properties of undefined (reading ‘postData’)
    というエラーが出ました。

    どなたか修正方法を教えていただけませんでしょうか、、

    • chaso chaso より:

      コメントありがとうございます。
      記載いただいたエラーは、GASのスクリプトエディタから「実行」を押して動かした時に発生するエラーです。

      本記事のサンプルソースは、LINEから画像データを受信した際に動くものですので、
      GASから実行するとエラーになります。
      LINEからメッセージを投稿して動作することを確認してみてください。

      またわからなければお気軽にコメントください!

      • ぶんぶく茶釜 より:

        早速のお返事ありがとうございます!コピペ用ソースコードで実際に作成してみます!

        • chaso chaso より:

          こちらこそ、試していただき嬉しいです♪

          GASのソースコードをデプロイしたときに生成されるURLをLINEに反映させるのを忘れないようご注意ください!
          あとは記事の内容通りに設定すれば動くはずです。
          よろしくお願いいたします!

          • ぶんぶく茶釜 より:

            コピペ用ソースコードをそのままGASに貼り付けて、デプロイしLINEのWebhook URLのところに入力してみましたがうまく動作しません、、、

            Googleドライブに画像ファイルがアップロードされ、OCR処理までは行えているのですが、DeepLの利用状況のところで利用文字数が1文字も増えていませんでした。
            またGoogleドライブ内にもLINEで送信した画像がそのまま残っていました。

            いろいろ調べてみたのですが、どうしても解決方法がわかりません、、、

          • chaso chaso より:

            Google Driveに残っている画像は、画像ファイルとして残っていますでしょうか?
            それとも、Google ドキュメント(Wordのような、文書ファイル)として残っていますか?
            LINEから取得した画像ファイルは、「Drive.Files.insert」で、GoogleドキュメントとしてGoogle Driveに保存されるのが正しいです。

            Googleドキュメントとして保存されるところまで成功しているのであれば、以下を試してみてください。

            下記のソースコードを、スクリプトの任意の場所に貼り付けて実行する
            ※実行する関数が「myFunction」になっているのを確認して実行してください!
            function myFunction() {
            var translatedText = deeplTranslate(‘Hello’);
            console.log(translatedText);
            }

            実行ログに翻訳結果が取得されれば、DeepL APIの利用が正しくできています。
            実行に失敗する場合はDeepL関係の設定に何か不備があると思われます。
            ひとまず、ここまで試してみていただけますでしょうか??

  3. ぶんぶく茶釜 より:

    早速のお返事ありがとうございます!
    Googleドライブにはtestというファイル名ののドキュメントとして保存されています。

    function myFunction() {
    var translatedText = deeplTranslate(‘Hello’);
    console.log(translatedText);
    }

    上記を追加したところ

    構文エラー: SyntaxError: Invalid or unexpected token
    と表示され、myFuncitonの関数を実行することが出来ませんでした、、、

  4. mtikirby より:

    やってみたのですが自動返信しか返ってこずうまくいきませんでした。なぜでしょう…

    • chaso chaso より:

      先日載せたソースコードは、GASの実行ログ上に実行結果を出力するものなので、
      GASから確認していただく形となります。
      GASの編集画面から「実行」を押したあと、画面下部に「実行ログ」が表示されますので、こちらをご確認ください。

      これは、DeepLのAPIとうまく通信できているか試す目的です。
      説明不足ですみません><。

タイトルとURLをコピーしました