Google Apps Scriptで画像から文字起こしを実現する【GAS】

機械学習サービスが現在最も熱いテクノロジーですが、Google提供のものは最も手軽に扱える上に、コストも激安なので、簡単に試せるのが良い点ですね。TensorFlowのようなものAutoML Visionといった高度なものから、前回紹介したCloud Speech APIなどなど豊富に用意されていて既に、実用化までされています。

今回は、画像認識用のAPIであるCloud Vision APIおよびGoogle Drive API付属のOCR機能を使って、画像から文字認識してテキストで取り出してみたいと思います。いずれも、Google Apps Script標準のAPIではないので、事前準備が必要です。

今回のサンプルファイルは、以前作成しました「Google Pickerでアップローダを作る」のサンプルファイルをベースにしています。また、似たようなものとして、音声から文字起こしも別のAPIで実現が可能です。

Google Picker アップローダを作る【GAS】

Google Apps ScriptとCloud Speech APIで文字起こし【GAS】

今回使用するファイルやサービス

Geminiを利用したOCR

このエントリー自体、生成AI登場前のAPIによる記事で、現在はGemini APIを使った生成AIを使ったOCRのほうが遥かに性能が上です。よって、Cloud Vision APIを使う手法が現時点ではあまり推奨できるレベルにありません。

細かな指示も出せるGemini APIを使ったOCRをお試しください。

AppSheetでアップしたPDFをGeminiでOCR

Google Drive APIを利用したOCR

プロジェクトを移動

今回の発表直前の2019年4月8日より、Google Apps ScriptからCloud Platform Projectへ直接アクセスが出来なくなりました。これまでにデプロイしてるものについては、これまで通り「リソース」⇒「Google Cloud Platform API ダッシュボード」からアクセスが可能です。

今回の変更はスプレッドシート上で動かすスクリプトやGoogleの拡張サービスを利用しないタイプのスクリプトであれば特に問題はありませんが、「Apps Script API」や「Google Picker API」、「Cloud SQL接続」などGCP上のAPIを利用する場合には以下の手順を踏んで、Google Apps Scriptにプロジェクトを連結する必要があります。これまでは、自動的にGCP上にGoogle Apps Script用のプロジェクトが生成されていたのですが、今後は自分の組織(もしくはGCPプロジェクト)上で作成されたプロジェクトでなければならないということです。詳細はこちらのページを見てください。

連結する手順は以下の通り

  1. Google Cloud Consoleを開く
  2. 左上にある▼をクリックする
  3. ダイアログが出てくるので、新規プロジェクトを作るか?既存のプロジェクトを選択する。この時、G Suiteであれば選択元は「自分のドメイン」を選択する必要があります。
  4. プロジェクト情報パネルから「プロジェクト番号」をコピーする
  5. 対象のGoogle Apps Scriptのスクリプトエディタを開く
  6. 「リソース」⇒「Cloud Platform プロジェクト」を開く
  7. 4.で入手した番号をプロジェクトを変更のテキストボックスに入れて、プロジェクトを設定ボタンをクリックする
  8. 無事に移動が完了すればメッセージが表示されます。
  9. この時、元の自動作成されたプロジェクトはシャットダウンされて消えます。これで設定完了です。

今回のこの変更だと1つ作ったプロジェクトに集約する必要があるので、クォータについてプロジェクト毎のカウントだったので問題なかったものが、集約されることで、クォータに引っ掛かる可能性があります。

図:プロジェクト番号をコピーしておきます

図:プロジェクトを他のプロジェクトに紐付けしました。

図:GCPの拡張サービスを使うには手順が必要になった

APIの有効化

Drive APIおよびPicker APIを利用しているので、これらをGoogle Apps Scriptから利用できるようにする必要があります。Pickerに関しては今回は省略します。以下の手順でDrive APIを利用可能な状態に準備しましょう。

  1. スクリプトエディタのメニューより「リソース」⇒「Googleの拡張サービス」を開きます。
  2. Drive APIのトグルをオンにします。
  3. 続けて、ダイアログ下部のGoogle Cloud Platform API ダッシュボードをクリックします。
  4. Cloud Console上部にある「APIとサービスの有効化」をクリックします。
  5. 検索画面にて、「Drive API」を探し出し、クリックしたら「有効にする」をクリックする
  6. 認証情報の作成は不要です。GASでは利用しません。

図:Drive APIを有効化しましょう。

ソースコード

GAS側コード

//アップロードされた画像ファイルからDrive APIを使ってOCR
function driveocr(fileid,filename,mimetype){
  var ui = SpreadsheetApp.getUi();
  
  //アップロードされた画像ファイルを取得する
  var blob = DriveApp.getFileById(fileid).getBlob();
  
  //画像ファイルのリソース設定
  var resource = {
    title: filename,
    mimeType: mimetype,
    parents:  [{"id": "ここに保存先親フォルダのIDを入力する"}],  //親フォルダ指定
  }

  // OCRオプション設定
  var option = {
    ocr: true
  };
  
  //画像をドライブに保存する
  var file = Drive.Files.insert(resource, blob, option);
  
  //生成ファイルから値を取得
  var doc = DocumentApp.openById(file.id);
  var text = doc.getBody().getText();
  
  //取得内容を書き込む
  var array = [];
  
  //uidを取得する
  var Prop = PropertiesService.getScriptProperties();
  var uid = Prop.getProperty("uid") + Number(1);
  array.push(uid);
  Prop.setProperty("uid", uid);
  
  //その他の情報をpushする
  var tarfile = "https://drive.google.com/open?id=" + fileid; 
  array.push(new Date());
  array.push(filename);
  array.push(tarfile);
  
  //取得したOCR結果をプッシュする
  array.push(text);
  
  //スプレッドシートに書き込む
  SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ocrtest").appendRow(array);
  
  //終了メッセージ
  ui.alert("OCRの結果を書き込みました。")
  
}

//Access Tokenを取得する
function getOAuthToken() {
  //DriveAppを参照させておく
  //https://issuetracker.google.com/issues/131443766
  var id = DriveApp.getRootFolder().getId(); 
  
  //DriveApp.addFile("test");

  //アクセストークンを取得する
  return ScriptApp.getOAuthToken();
}
  • optionには、ocrLanguageというオプションもあるのですが、現時点ではこれを追加するとサーバーエラーが置きますので、今回のコードでは除外しています。
  • Drive APIを利用してOCRオプションを設定している為、指定のフォルダにはGoogle DocumentによるOCR結果が生成されています。
  • Picker側でアップロードしたファイルのID、ファイル名、MimeTypeを取得してdriveocr関数へ引き渡してあげています。

HTML側コード

<link href="https://ssl.gstatic.com/docs/script/css/add-ons.css" rel="stylesheet" />
<script type="text/javascript" src="https://apis.google.com/js/api.js"></script>

<script type="text/javascript">
  var DEVELOPER_KEY = 'Picker APIで設定したAPIキーをここに入力';
  var DIALOG_DIMENSIONS = {width: 750, height: 450};
  var pickerApiLoaded = false;
  var origin = google.script.host.origin;
  var parent = "画像ファイルをアップロードする先のフォルダのIDをここに入力";
 
  //Google Picker API呼び出し
  gapi.load('picker', {'callback': function() {
    pickerApiLoaded = true;
  }});
 
  //ドラッグエリアを表示する
  google.script.run.withSuccessHandler(createPicker).withFailureHandler(showError).getOAuthToken();
 
  //Picker Dialogを表示する
  function createPicker(token) {
    if (pickerApiLoaded && token) {
      var uploadView  = new google.picker.DocsUploadView().setParent(parent);
      
      //アップロードファイルのMIMETYPEを制限
      uploadView.setMimeTypes("image/png,image/jpeg,image/jpg");
      
      var picker = new google.picker.PickerBuilder()
            .addView(uploadView)
            .hideTitleBar()
            .setOAuthToken(token)
            .setOrigin(origin)
            .setLocale("ja")
            .enableFeature(google.picker.Feature.NAV_HIDDEN)
            .enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
            .setDeveloperKey(DEVELOPER_KEY)
            .setCallback(pickerCallback)
            .setSize(DIALOG_DIMENSIONS.width - 10,
                     DIALOG_DIMENSIONS.height -10)
            .build();
      picker.setVisible(true);
    } else {
      showError('Pickerをロード出来ませんでした。');
    }
  }
 
  //Callbackデータを受け取る
  function pickerCallback(data) {
    if (data.action == google.picker.Action.PICKED) {
      var length = data.docs.length;
      var urlbase;
      
      for(var i = 0;i<length;i++){
        var fileId = data.docs[i].id;
        var url = data.docs[i].url;
        var title = data.docs[i].name;
        var mime = data.docs[i].mimeType

        //アップロード完了メッセージ 
        urlbase = "https://drive.google.com/file/d/" + fileId + "/view?usp=sharing"
        document.getElementById('result').innerHTML +=
            '<b>アップロードしたファイル:</b><br />ファイル名: <a href="' + urlbase + '" target="_blank">' + title + '</a><br />ID: ' + fileId + '<br>';
        
        //GAS側へ処理を引き継ぐ
        google.script.run.driveocr(fileId,title,mime);
        //google.script.host.close();
        
      }
    } else if (data.action == google.picker.Action.CANCEL) {
      google.script.run.messager("アップロードはキャンセルされました。");
    }
  }
 
  //エラー表示用
  function showError(message) {
    document.getElementById('result').innerHTML = 'Error: ' + message;
  }
</script>

<div id = "result"></div>
  • 今回のPicker APIでは、jpeg画像およびpng画像だけを選択できるように制限を加えています。
  • アップロードが完了すると、GAS側のdriveocr関数へと値を引き渡して処理を続行します。
  • 複数選択可能にしていますが、今回のルーチンはGAS側で表示させているので、複数ファイルの処理には対応させていません。
  • Picker用のAPIキーが必要です。

読み取り精度について

出勤簿のサンプル画像ファイルをアップロードしてみました(手書きで出勤データを記述しています。)。結果生成されたドキュメントはこんな感じ。。。正直なところ、実用レベルには無いです。業務などで利用するこの手の帳票類でDrive APIのOCR機能では、読み取りは可能ですが、後処理がとても大変。そこで、青空文庫の文章モノならと太宰治の「富嶽百景」を画像として読み込ませました。

図:富嶽百景の冒頭を切り取って画像化してみた

富嶽百景 太宰治 「ひろしげ ぶんてう きやしや 「わし 富士の頂角、広重の富士は八十五度、文泉の富士も八十四度くらる、けれども、陸軍の実測図によつて東西及南北に断面図を作ってみると、東西縦断は頂 角、百二十四度となり、南北は百十七度である。広重、文泉に限らず、たいていの絵の富士は、鋭角である。いただきが、細く、高く、華奢である。北斎にい たつては、その頂角、ほとんど三十度くらる、エッフェル鉄塔のやうな富士をさへ描いてある。けれども、実際の富士は、鈍角も鈍角、のろくさと拡がり、東 西、百二十四度、南北は百十七度、決して、秀抜の、すらと高い山ではない。たとへば私が、印度かどこかの国から、突然、鷲にさらされ、すとんと日本の沼津 * あこが あたりの海岸に落されて、ふと、この山山を見つけても、そんなに驚嘆しないだらう。ニッポンのフジヤマを、あらかじめ憧れてあるからこそ、ワンダフルなの であって、さうでなくて、そのやうな俗な宣伝を、一さい知らず、素朴な、純粋の、うつろな心に、果して、どれだけ訴へ得るか、そのことになると、多少、心 細い山である。低い。裾のひろがってるる割に、低い。あれくらるの裾を持ってある山ならば、少くとも、もう一・五倍、高くなければいけない。 「十国峠から見た富士だけは、高かった。あれは、よかった。はじめ、雲のために、いただきが見えず、私は、その裾の勾配から判断して、たぶん、あそこあた りが、いただきであらうと、雲の一点にしるしをつけて、そのうちに、雲が切れて、見ると、ちがった。私が、あらかじめ印をつけて置いたところより、その」 倍も高いところに、青い頂きが、すっと見えた。おどろいた、といふよりも私は、へんにくすぐったく、げらげら笑った。やってるやがる、と思った。人は、完 全のたのもしさに接すると、まづ、だらしなくげらげら笑ふものらしい。全身のネヂが、他愛なくゆるんで、之はをかしな言ひかたであるが、帯紐といて笑ふ といつたやうな感じである。諸君が、もし恋人と逢って、逢ったとたんに、恋人がげらげら笑ひ出したら、慶祝である。必ず、恋人の非礼をとがめてはならぬ。 恋人は、君に逢って、君の完全のたのもしさを、全身に浴びてみるのだ。 東京の、アパートの窓から見る富士は、くるしい。冬には、はつきり、よく見える。小さい、真白い三角が、地平線にちよこんと出てるて、それが富士だ。な んのことはない、クリスマスの飾り菓子である。しかも左のはうに、肩が傾いて心細く、船尾のはうからだんだん沈没しかけてゆく軍艦の姿に似てるる。三年ま への冬、私は或る人から、意外の事実を打ち明けられ、途方に暮れた。その夜、アパートの一室で、ひとりで、がぶがぶ酒のんだ。一睡もせず、酒のんだ。あか つき、小用に立つて、アパートの便所の金網張られた四角い窓から、富士が見えた。小さく、真白で、左のはうにちよつと傾いて、あの富士を忘れない。窓の下 のアスファルト路を、さかなやの自転車が疾駆し、おう、けさは、やけに富士がはっきり見える写やねえか、めつぽふ寒いや、など咳きのこして、私は、暗い 便所の中に立ちつくし、窓の金網撫でながら、じめじめ泣いて、あんな思ひは、二度と繰りかへしたくない。 昭和十三年の初秋、思ひをあらたにする覚悟で、私は、かばんひとつさげて旅に出た。 おびひも むな

なかなか良い精度だけれど、旧仮名遣いやルビのせいでおかしな読み取りをしている部分などがいくつか見受けられる。恐らく旧漢字も読めないだろうと思われる。連続した文章を読み込ませるのであれば、Drive APIのOCR機能は悪くない印象です。但し、手書きではなく、コンピュータで打たれた文字ならばの話ですが。

Google Cloud Vision APIを利用したOCR

Cloud Vision APIの概要

Googleが提供している機械学習を行う画像認識APIがCloud Vision APIです。単に画像から文字起こしだけでなく、画像を認識して処理するような事まで幅広く担当しているAPIですが、Speech API同様課金対象のAPIです。ですが、月間の無料枠があるので、その枠内であれば、課金されたり、また勝手に課金されるといった事はありません。料金はこちらから。用途別で変わってきます。今回は、OCRについてだけ取り上げてみたいと思います。

また、テキスト検出についてのサンプルなどはこちらのページに用意されています。

項目名 内容
画像ファイル JPG形式,  PNG形式(但し、640x480以上のサイズであること)
ファイルサイズ 20MBまで(返り値のJSONオブジェクトは10MBまで)。また1リクエストあたり16枚まで。
リクエスト Base64形式で渡すか?Cloud Storageへ配置する必要がある
無償上限単位 1000ユニット/月まで。それ以上は課金対象(1画像1ユニット)
有償課金 1.5ドル/月(500万ユニットまで)
制限 1分あたり1,800枚まで。1ヶ月あたり20,000,000 枚まで

事前準備

OAuth2.0認証ライブラリの追加

今回のサービスは、OAuth2.0認証が必要です。以下の手順でOAuth2 for Apps Scriptライブラリを追加しましょう。

  1. スクリプトエディタを開きます。
  2. メニューより「リソース」⇒「ライブラリ」を開きます。
  3. ライブラリを追加欄に「1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF」を追加します。
  4. 現時点ではバージョンは30が最新ですので、それを選択しておきます。
  5. 保存ボタンを押して完了

これで、OAuth2.0認証にまつわる様々な関数を手軽に利用できるようになります。

図:ライブラリを追加した様子

サービスアカウントの作成

今回のスクリプトの準備で最も面倒なのはこのサービスアカウントの作成です。サービスアカウントの作成自体は以前Google Cloud Consoleを弄ってみるの回で紹介しています。ですが、今回改めてCloud Vision APIの利用まで含めて特殊なコードが必要なので、ここで紹介いたします。今回はサービスアカウント方式を利用していますが、シンプルなAPI方式もあります(ただし有償課金サービスなので、よりセキュアなこの方式を推奨します)

  1. スクリプトエディタを開き、「リソース」⇒「Googleの拡張サービス」を開く
  2. ダイアログ下にある「Google Cloud Platform API ダッシュボード」を開く
  3. APIとサービスの有効化」をクリックする
  4. visionで検索し、「Cloud Vision API」をクリックする。
  5. 請求の有効化画面が出るので「請求アカウントの作成」をクリック
  6. ウィザードに従い、同意して続行しクレジットカード情報を登録します。
  7. プロジェクトへの認証情報の追加画面では、Cloud Vision APIを選択し、App Engineで使う予定の問いには、「いいえ」で答える
  8. 次のステップではサービスアカウントの名前を入力。わかりやすい名前をつけましょう。キーのタイプはJSONを選択
  9. サービスアカウントの役割では、Project編集者を選択します。
  10. JSONファイルがダウンロードされるので、これを誰とも共有しない形で、Google Driveにアップロードします(Google Cloud Storageも可能です)。流出すると後で課金で痛い目を見るので絶対に共有はしないでください。
  11. アップロードしたJSONファイルの直URLを取得する。https://drive.google.com/open?id=に続けてファイルのIDをつなげればOKです。
  12. 次の項目のJSONキーファイルを取得して認証するにて、冒頭のfilelinkの場所にこのURLを入れてあげる。

図:Cloud Vision APIの有効化画面

図:請求アカウントを作らなければいけません

図:サービスアカウント方式ではなくAPI方式もあります

図:サービスアカウントの権限はできる限り最小で

JSONキーファイルを取得して認証する

//認証用各種変数
var tokenurl = "https://accounts.google.com/o/oauth2/token"
var filelink = "ここにDriveにアップしたJSON KeyファイルのURLを入力する";   //JSON Keyファイルを指定

//OAuth2認証を実行する
function startoauth(){
  //UIを取得する
  var ui = SpreadsheetApp.getUi();
  
  //認証を実行する
  var service = checkOAuth();
  ui.alert("認証が完了し、Access Tokenを取得しました。")
}

//Google DriveにあるサービスアカウントキーのJSONファイルを取得する
function getServiceAccKey(){
  //filelinkからFileIDを取得する
  var fileId = filelink.match(/[\w-]{25,}/)[0];
  
  //JSONファイルの中身を取得する
  var content = DriveApp.getFileById(fileId).getAs("application/json").getDataAsString();
  return JSON.parse(content);
}

//OAuth2.0認証を実行する
function checkOAuth() {
  //JSONファイルの中身を取得する
  var privateKeys = getServiceAccKey();
  
  return OAuth2.createService('GoogleCloud:' + Session.getActiveUser().getEmail())
  //アクセストークンの取得用URLをセット
  .setTokenUrl(tokenurl)
  
  //プライベートキーとクライアントIDをセットする
  .setPrivateKey(privateKeys['private_key'])
  .setIssuer(privateKeys['client_email'])
  
  //Access Tokenをスクリプトプロパティにセットする
  .setPropertyStore(PropertiesService.getScriptProperties())
  
  //スコープを設定する
  .setScope('https://www.googleapis.com/auth/cloud-platform');
}
  • スプレッドシートのメニューより「OCRテスト」⇒「サービスアカウント認証」を実行してください。いつもどおりの認証画面ですが、バックエンドでは自動でAccess Tokenの取得が行われます。
  • この認証方式はサービスアカウントが認証を行うので、いつものユーザが認証するものとは異なり、Access Token取得は自動で行われます。
  • 取得したアクセストークン等の塊は、OAuth2ライブラリ最新版より、スクリプトプロパティではなくユーザプロパティに格納されているので、より安全になっています。塊は、var service = checkOAuth();で呼び出せます。

画像ファイルについて

画像ファイルですが、直接渡すことができません。Cloud Storageに配置するか?もしくは、Base64エンコードしたデータで渡す必要性があります。また、その場合もGoogle Driveに一旦アップロードしてから、Base64エンコードする必要があります。

Google Apps ScriptにはBase64エンコードするメソッドがあるのでそれらを組み合わせて、Cloud Vision APIに対してデータを送信するようにコードを記述しましょう。

ソースコード

GAS側コード

//アップロードされた画像ファイルからCloud Vision APIでOCR
function visionocr(fileId,title,mime){
  var ui = SpreadsheetApp.getUi();
  
  //ファイルの情報と言語の設定
  var file = DriveApp.getFileById(fileId);
  var bytes = file.getBlob().getBytes();
  
  //OAuth認証情報を取得
  var service = checkOAuth();
  
  //ファイルデータをbase64でエンコードする
  var b64 = Utilities.base64Encode(bytes);
  var dataman = {
    requests:[
      {
        image:{
          content: b64
        },
        features:{
          type: "TEXT_DETECTION",
          maxResults: 100
        }
      }
    ]
  }

  //ファイル情報を構築
  var payload = JSON.stringify(dataman);
  
  //画像ファイルをAPIへ渡す
  if (service.hasAccess()) {
    //Access Tokenを取得
    var accessToken = service.getAccessToken();
    
    try{
      //POSTで通信
      var url = "https://vision.googleapis.com/v1/images:annotate";
      var response = UrlFetchApp.fetch(url, {
        method: 'POST',
        headers: {
          Authorization: 'Bearer ' + accessToken
        },
        contentType: "application/json",
        payload: payload,
        muteHttpExceptions: true
      });
      
      //変換結果を取得する
      var result = JSON.parse(response.getContentText());

      //エラー発生時に捕捉する
      if (result.error && (result.error.code == '401' || result.error.code == '403' || result.error.code == '400') ) {
        ui.alert(result.error.status + "\n\n" + result.error.message);
        return;
      }
      
      //結果をメッセージで表示
      var array = [];
      
      //uidを取得する
      var Prop = PropertiesService.getScriptProperties();
      var uid = Prop.getProperty("uid") + Number(1);
      array.push(uid);
      Prop.setProperty("uid", uid);
      
      //その他の情報をpushする
      var tarfile = "https://drive.google.com/open?id=" + fileId; 
      array.push(new Date());
      array.push(title);
      array.push(tarfile);
      
      //取得したOCR結果をプッシュする
      var ocr = result.responses[0].fullTextAnnotation.text;
      array.push(ocr);

      //スプレッドシートに書き込む
      SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ocrtest").appendRow(array);
      
      //終了メッセージ
      ui.alert("OCRの結果を書き込みました。")

    }catch(e){
      ui.alert("error:" + e.message);
    }
  }
}
  • 取得したファイルは、Base64エンコードを行い、渡します。そのままファイルのデータを渡すことができません。
  • OCRの場合には、Featureについては「TEXT DETECTION」でもってAPIに値を渡します。
  • Vision APIのエンドポイントURLは、https://vision.googleapis.com/v1/images:annotateです
  • レスポンスで帰ってきたJSON値に対して、result.responses[0].fullTextAnnotation.textにて値を取り出しています。複数ファイルには今回コードで対応させていないので、responseのとり方に注意です。
  • レスポンスには、細かくその画像のXY座標と認識結果も付いてきます。他の要素(例えば検出範囲の指定するようなコード)と合わせて、検出するものがどういった項目なのかを定義できれば、名刺読み取りアプリのようなものが作れるでしょう。

対応している画像認識機能

分析タイプ 内容
LABEL_DETECTION 画像内にある様々な物体のカテゴリを認識する
TEXT_DETECTION 画像内にあるテキストを検出するOCR機能
FACE_DETECTION 顔の認識機能。顔以外の服などの属性情報も取れる
LANDMARK_DETECTION ランドマークや自然の構造物の検出
LOGO_DETECTION 商品ロゴや企業ロゴの検出をする
SAFE_SEARCH_DETECTION 不適切な検索結果の検出
IMAGE_PROPERTIES 画像の属性を検出
WEB_DETECTION 類似の画像をネットで検索する機能

エラーについて

API呼び出し時には、コードが正しく書かれていない場合、今回のソースコードの事例ですと、400,403,404のエラーについては捕捉してその内容を表示するようにしています。その中で下記のようなエラー(Permission Denied)がでた場合には、きちんとプロジェクトが請求アカウントに紐付けされていない為に発生するエラーです。

エラーの内容にあるURLへアクセスし、請求アカウントのリンクをしてください。基本的にはクリックするだけで、リンクされるはずです。但し、この時請求アカウントにリンクの出来るプロジェクト数には限りがあるので、リンクできなかった場合には、不要なプロジェクトを削除し、リンクの解除をしてあげてから、リンクを行う必要があります。

 

図:Permission Deniedのエラー

図:請求アカウントにリンクする青いボタン

読み取り精度について

Drive APIの時と同様に、出勤簿画像と青空文庫の画像ファイルを読み込ませてみました。

前者については、期待したのですが、Drive APIの時よりも悪い結果に・・・得手不得手があるようですね。手書きのものに対する認識率がすこぶる悪かったです。

後者の場合、Drive APIよりも良い結果になりました。旧仮名遣いも問題なく、恐らく旧漢字でもしっかり認識するのではないかと思います。ルビについてはそういう行として認識されているようですね。

富嶽百景
太宰治
ひろしげ
ぷんてう
富士の頂角、広重の富士は八十五度、文晁の富士も八十四度くらゐ、けれども、陸軍の実測図によって東西及南北に断面図を作ってみると、東西縦断は頂
角、百二十四度となり、南北は百十七度である。広重、文晁に限らずたいていの絵の富士は、鋭角である。いただきが、細く、高く、華奢である。北斎にい
たっては、その頂角、ほとんど三十度くらゐ、エッフェル鉄塔のやうな富士をさへ描いてゐる。けれども、実際の富士は、鈍角も鈍角、のろくさと拡がり、東
西、百二十四度、南北は百十七度、決して、秀抜の、すらと高い山ではない。たとへば私が、印度かどこかの国から、突然、鷲にさらはれ、すとんと日本の沼津
あたりの海岸に落されて、ふと、この山を見つけても、そんなに驚嘆しないだらう。ニッポンのフジヤマを、あらかじめ憧れてゐるからこそ、ワンダフルなの
であって、さうでなくて、そのやうな俗な宣伝を、一さい知らず、素朴な、純粋の、うつろな心に、果して、どれだけ訴へ得るか、そのことになると、多少、心
細い山である。低い。裾のひろがつてゐる割に低い。あれくらゐの裾を持つてゐる山ならば、少くとも、もう一·五倍、高くなければいけない。
きゃしゃ
インド
わし
あこカ
十国峠から見た富士だけは、高かった。あれは、よかった。はじめ、雲のために、いただきが見えず私は、その裾の勾配から判断して、たぶん、あそこあた
りが、いただきであらうと、雲の一点にしるしをつけて、そのうちに、雲が切れて、見ると、ちがった。私が、あらかじめ印をつけて置いたところより、その
倍も高いところに、青い頂きが、すっと見えた。おどろいた、といふよりも私は、へんにくすぐったく、げらげら笑った。やってゐやがる、と思った。人は、完
全のたのもしさに接すると、まづ、だらしなくげらげら笑ふものらしい。全身のネヂが、他愛なくゆるんで、之はをかしな言ひかたであるが、帯紐といて笑ふ
といったやうな感じである。諸君が、もし恋人と逢って、逢ったとたんに、恋人がげらげら笑ひ出したら、慶祝である。必ず恋人の非礼をとがめてはならぬ。
恋人は、君に逢って、君の完全のたのもしさを全身に浴びてゐるのだ。
しるし
おびひも
東京の、アパートの窓から見る富士は、くるしい。冬には、はっきり、よく見える。小さい、真白い三角が、地平線にちょこんと出てゐて、それが富士だ。な
んのことはない、クリスマスの飾り菓子である。しかも左のはうに、肩が傾いて心細く、船尾のはうからだんだん沈没しかけてゆく軍艦の姿に似てゐる。ニ,,
への冬、私は或る人から、意外の事実を打ち明けられ、途方に暮れた。その夜、アパートの一室で、ひとりで、がぶがぶ酒のんだ。一睡もせず酒のんだ。あか
つき、小用に立つて、アパートの便所の金網張られた四角い窓から、富士が見えた。小さく、真白で、左のはうにちょっと傾いて、あの富士を忘れない。窓の下
のアスファルト路を、さかなやの自転車が疾駆し、おう、けさは、やけに富士がはっきり見えるぢゃねえか、めっぽふ寒いや、など呟きのこして、私は、暗い
便所の中に立ちつくし、窓の金網撫でながら、じめじめ泣いて、あんな思ひは、二度と繰りかへしたくない。
つぶや
昭和十三年の初秋、
思ひをあらたにする覚悟で、
私は、
かばんひとつさげて旅に出た。

今回は、OCRに注目しAPIを利用しましたが、このCloud Vision APIは、他のAPIとの連携や、例えばレシートの読み込み、画像ファイルからの判断などの機械学習によって成長するAPIです。OCR以外の機能も豊富なのでむしろ、そちらの方向性で使ったほうが良いのではないかと思います。

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)