【kintone x OCR】~KEYWORD検索編~ kintoneのOCRプラグインを開発する②【GCP】

無償で試してみる

下記に「アカウント申請」という件名(本文なし)でメールを送付頂ければ、数分程度でアカウント情報を返信します。 ocr.lastonemile@gmail.com * 利用規約に同意の上、ご利用ください。 https://tanoshimane.stores.jp/news/603313afc19c4527490eb72e * kintoneというクラウドアプリ上に構築しており、そのゲストIDを発行します。 * 30日間又は100ページまで(kintoneの利用料含めて)無償で利用可能です。

詳細:https://qiita.com/Lastonemile/items/65b9102c868e09b3248e

プラグインのダウンロード

kintone用OCRプラグイン及びテンプレートが、下記よりダウンロード(無償で購入)可能です。

利用(設定)方法

最終目標

kintone上でこの↓画像(請求書)をOCR処理し、請求番号・支払期限・振込先・請求元・明細(品名・数量・・・のテーブル部分)の値を取得することを最終目標とします。 請求書サンプル.jpg

尚、説明は後回しで「まず試したい」という方は、プラグイン(テンプレート)のダウンロードからkintone用のプラグインとテンプレートを試用(1か月間)頂けます。

今回(KEYWORD検索編)の目標

①でCloud VisionOCR結果をKintone上で取得するプラグインを作成しました。 今回はその結果を利用して、必要な情報(請求番号・支払期限・振込先・請求元・明細)を取得していこうと思います。

早速ですが、取得する方法はいくつか考えつきます。(私の知識の範囲ですが)下記に列挙してみたいと思います。

①AI(機械学習)を利用して取得する。 ②決まった文字列(KEYWORD)を利用して取得する。 ③座標(ZONE)を利用して取得する。 ④正規表現を利用して取得する。

先に記載しておきますが、①については今の私の頭では無理なので、不採用とします。(私見ですが、①の方法は構築難度もさることながら、学習データの準備や補正等、余程の大会社でなければ現実的には利用段階にはないと思います)

残りの②~④については、(後述しますが)それぞれ得手不得手があります。そこで最終的には、それぞれを補完するために②~④を組み合わせることで、精度を高めていきたいと思いますが、今回のKEYWORD検索編では「②決まった文字列(KEYWORD)を利用して取得する」方法にフォーカスしてご説明したいと思います。

KEYWORD検索の定義

例として上の請求書の請求番号を取得したいとします。 請求番号.PNG 当然、取得したい請求番号の値(今回であれば123456789)については、請求書が変わるたびに変化します。しかし、必ず「請求番号」という項目名(KEYWORD)の右側に値が記載されています。

このようにKEYWORDを手掛かりに取得する方法をKEYWORD検索と定義します。

ちなみに、次の記事で「座標(ZONE)を利用」する方法も紹介しますが、この「座標(ZONE)を利用」方法に対するKEYWORD検索のメリットはKEYWORDの位置が変わっても、文書上にKEYWORDが存在していれば、値を取得できるところにあります。

尚、今回も①に引き続きkintone上でCloud Visionを利用している想定で、Cloud Visionのresponseから値を取得する前提で話を進めていきます。 kintone上でのCloud Visionの利用(前回記事):https://qiita.com/Lastonemile/items/55e6a159a4c2bcc9dab4

具体的な取得方法、その前に

Cloud Visionのresponseには、文字(description)だけでなく、座標含め様々な情報が記載されています。

//response 例(引用)
{
      "responses": [
        {
          "textAnnotations": [
            {
              "locale": "en",
              "description": "WAITING?",
              "boundingPoly": {
                "vertices": [
                  {
                    "x": 352,
                    "y": 828
                  },
                  {
                    "x": 2248,
                    "y": 911
                  },
                  {
                    "x": 2238,
                    "y": 1148
                  },
                  {
                    "x": 342,
                    "y": 1065
                  }
                ]
              }
            }
        ]
      }
   ]
}
            

そのため、今回は不要な部分を削除し、こんな感じ↓のわかりやすいjsonに書き換えます。以後はこのjson形式になっているresponseを扱う前提で話を進めていきたいと思います。

{"String":"description","x1":0,"x2":1,"x3":1,"x4":0,"y1":0,"y2":0,"y3":1,"y4":1}

*座標は最小0,最大1で定義しました。(x1y1:左上・x2y2:右上・x3y3:右下・x4y4:左下になります)

具体的な取得方法

座標を利用することで、"「請求番号」というKEYWORDの右側"を指定できます。手順は下記のようになります。

①KEYWORD(今回は「請求番号」という文字列)の座標を取得する。 ②その座標の右側にある文字列(複数)を取得する。 ③②で取得した文字列(複数)のなかから、最も位置が近い文字列を取得する。

①については、単純にKEYWORDと一致する又はKEYWORDに最も近い文字列を検索し、その座標を取得します。

②を行うためには、まず"右側"を定義する必要があります。今回はKEYWORDのx2よりx1が大きく(右にあり)、KEYWORDのy2よりもy4が大きく(下にあり)、KEYWORDのy3よりもy1が小さい(上にある)文字列を"右側"と定義しました。*言葉にすると分かりにくいですね。

for(let i = 0; i < list.length; i++){
   if(keyword.x2 < list[i].x1 && keyword.y2 < list[i].y4 &&  keyword.y3 > list[i].y1){
      result_list.push(list[i]);
   }
}

右側図解.PNG

例えば、今回の文書が(仮に)右肩上がりに傾いていた場合、「請求日」の「2020/1/1」も①の範囲内(「請求番号」の右側)に入る可能性があります。そのような場合の対応が③になります。 ちなみに、「最も近い」というのは、文書の左上を始点としてそこからの距離が最も近いものを「最も近い」と定義しました。

ここまで、"右側"の取得方法について説明しましたが、当然取得したい値の全てがKEYWORDの右側にあるわけではありません。方向で考えると右以外に下も考えられます(今回だと、「振込先」なんかは下になります)ので、"右側"と同様の考え方で下も定義しました。

for(let i = 0; i < list.length; i++){
   if( keyword.y3 < list[i].y1){
      result_list.push(list[i]);
   }
}

また、右と下の方向は定義しましたが、その中でも、取得したい値が1つの文字列か複数かでも取得方法が変わってきます。具体的には「請求番号」は1つの文字列ですが、「振込先」の値は複数の文字列(複数行)になっています。

そこで、複数の文字列を取得する場合には、「③②で取得した文字列(複数)のなかから、最も位置が近い文字列を取得」ではなく、「③②で取得した文字列(複数)の中から、指定する範囲まで取得」することとします。尚、この「指定する範囲」についても、KEYWORD(LIMIT KEYWORDと呼びます)を利用して指定します。

for(var i = 0; i < list.length; i++){
   if( keyword.y3 < list[i].y1 && limit_keyword.y1 > list[i].y3){
      result_list.push(list[i]);
   }
}

KEYWORD検索での取得方法まとめ

書きながら、私もこんがらがってきたので、少しまとめます。

・KEYWORD検索での取得方法には、右、右複数、下1行、下複数の4パターンがあり、それぞれKEYWORDの座標をもとに指定する。 ・対象が1つの文字列(右、下1行)の場合は、KEYWORDに最も近い文字列を取得する。 ・対象が複数の文字列(右複数、下複数)の場合は、LIMIT KEYWORDを定め、その座標までの範囲の文字列を取得する。

kintoneアカウントを持っていない方

ここまでの説明及び、以降の記事内容も網羅したOCRシステムが、メールアドレス登録のみでご利用いただけます。 OCRシステム ユーザー登録: https://qiita.com/Lastonemile/items/65b9102c868e09b3248e

kintoneアカウントを持っている方

プラグイン(テンプレート)のダウンロード

ここまでの説明及び、以降の記事内容も網羅したkintone用OCRプラグイン及びテンプレートが、下記よりダウンロード(無償で購入)可能です。

利用方法:https://qiita.com/Lastonemile/items/c40cdd8543f14496c0c4

IEではご利用いただけませんChrome,edgeは動作確認済、その他ブラウザは未検証です) *初回利用時から1か月間無償でご利用いただけます。 *ご利用にあたり、ご利用者のドメイン情報を取得します(ドメイン毎に利用期間を管理しています)。 *利用にあたり、別途Google Cloud VisionAPIキーを取得頂く必要がございます。(取得代行も行っています) Cloud Visionの詳細:https://cloud.google.com/vision/docs?hl=ja *利用時にCloud Visionの利用料金が発生する可能性があります。(2020/12/24現在 月間1000ユニットまで無料で利用可能です。) Cloud Vision API料金:https://cloud.google.com/vision/pricing?hl=ja APIキー取得方法:https://tanoshimane.stores.jp/news/602220196728be15433783e4 APIキーの管理には十分ご注意ください(自己責任でお願いします)

今後の課題

KEYWORD検索の方法は分かったけど、KEYWORD検索だけじゃ全ての値を取得できないよね? と、感想をお持ちの方が多いのではないかと思います。

今回の最終目標でいえば、KEYWORD検索で「請求番号」「支払期限」「振込先」の値は取得出来そうですが、それ以外はKEYWORD検索だけでは難しそうです。

KEYWORD検索にはいくつかデメリットがあります。その中でも一番大きなものは、単純に「KEYWORDがない場合は、どうすればいいの?」であり、今回の例で考えると「請求元」がそれにあたります。

そこで、次回はKEYWORDがない場合に、どのように値を取得するか?を記載したいと思います。

ここまでで出来たこと

KEYWORD検索.PNG *KEYWORD検索で取得出来る値(請求番号・支払期限・振込先)が取得できるようになりました。

筆者の紹介

群馬県渋川市高崎市を中心に群馬県内でkintoneを利用したDX化支援を行っています。ご興味ある方はぜひご連絡ください。 https://ks-kiki.hp.peraichi.com/

関連記事

kintone OCRプラグイン Vision API arr.by LOM 利用方法 kintone OCRプラグイン 文書テンプレート作成方法 kintoneのOCRプラグインを開発する①