前回は、GoogleCloudのOCR機能を試しましたが、今回はAzure版です。
なんかタイトル長いですが、実はAzureのOCR機能の正式サービス版はまだ日本語に対応しておらず、いわゆるプレビュー版でしか日本語指定の読み取りができないんですねー
プレビュー版はドキュメントが別になってるので、探して実装するのにちょっぴり苦労しましたー?
参考:Computer Vision API (v3.2-preview.1)
例の如く、このページからAzure Computer Vision v3.2-preview.1 APIの呼び出しができます!?
(このページはVueで書いたのでIEだと動きません。)
まずは実装したものが、こちら↓↓↓ 解説は後半で。
?解説
今回も、中継サービスにはGoogleのCloud Functionsを使っています。
今回はAzureの記事だから本当ならAzure Functionsで実装したかったけども、Azure Functionsだと無料枠超えてしまった時の課金額が高いから。。。?
Google Cloud | Azure | |
---|---|---|
無料枠 | 最初の 200 万回/月 | 100 万実行回数/月 |
超えた場合の料金 | 100万回あたり$0.40 | 100 万実行回数あたり ¥22.400 |
参考・・・(2020/12/21時点)
ちょっと実装したくらいで無料枠は超えないと思うけどね、公開する以上どんな攻撃受けるかわからんし、上限超えたとたんに2万円はちょっと個人には大きいかなと・・・?
全体の動きは、こんな感じになってます。
?まず、なぜプレビュー版のバージョンを使ったのか?
実は、まだAzureのOCR機能って日本語に対応してなかったんですねー
現時点でGAしているComputer Vision API (v3.1)では、まだ読み取りオプションにjaが含まれていません。
現在プレビュー版になっているComputer Vision API (v3.2-preview.1)から、読み取りオプションにjaが追加されています。
で、ドキュメントを読んでくとプレビュー版に関してはREST APIを使う感じになっていてAzure環境内に閉じるメリットも特にないんですよね。(Google Vision APIはFunctionsなど同一プロジェクト内での呼び出しに関してはAPIキーの生成は不要だった。)
?1回の呼び出しじゃ結果まで取得できない。
上のフローで書いた通りREST APIでの呼び出しの場合、POST送信1発でOCR結果が返ってきません!
本当はFunctions側で再帰的にOCR完了まで待機させたかったところですが、実行時間が長くなると無料枠のランタイムを無駄遣いしてしまうことになるのでボタンを2回押す作りにしました。
- ブログサイトから画像をPOST
- FunctionsでREST APIキーを付加してOCRへPOST転送
- Computer VisionがOCR読取を開始し「apim-request-id」を発行
- ブログサイトから「apim-request-id」の結果をGETリクエスト
- FunctionsのREST API経由でComputer VisionからOCR結果を取得
GET取得が早すぎると、status:runningってのが返ってきてOCR結果が得られません。
ちなみに、OCR結果のデータは48時間以内に削除されるそうです。
?実際にやってみた。
前回と同じ画像でやってみました。
結果は、こんな感じになりました。
(表示ルールは、前回記事と同様です。)
confidence値が低めでピンクになっちゃってるところが目立つ感じですかねぇ。
?Google Cloud Functions側のコード(一部抜粋)
基本的には、前回のコードをパクった感じになってます。
POSTとGETでプロセスが変わる感じになってます。
REST APIなので、subscription_keyをセットしてPOST・GET用のエンドポイントにリクエストを投げてます。
REST APIの結果はそのままjson変換できたので前回のGoogle Visionよりそのまんまの状態で応答全文を画面表示できてます。
def callAzureComputerVision(request): """Responds to any HTTP request. Args: request (flask.Request): HTTP request object. Returns: The response text or any set of values that can be turned into a Response object using `make_response <http://flask.pocoo.org/docs/1.0/api/#flask.Flask.make_response>`. """ # Set CORS headers for preflight requests if request.method == 'OPTIONS': # Allows GET requests from origin https://mydomain.com with # Authorization header headers = { 'Access-Control-Allow-Origin': 'https://yizm.work', 'Access-Control-Allow-Methods': 'POST, GET', 'Access-Control-Allow-Headers': 'Content-Type', 'Access-Control-Max-Age': '3600' } return ('', 204, headers) if request.method == 'POST' : # Set CORS headers for main requests res_headers = { 'Access-Control-Allow-Origin': 'https://yizm.work' } rslt = {} headers = {"content-type": "application/json"} pst_headers = { 'Ocp-Apim-Subscription-Key': subscription_key, 'Content-Type': 'application/octet-stream' } strm = request.files['fname'].stream read_result = requests.post(post_endpoint, data=strm.read(), headers=pst_headers) return ({ 'apim-request-id': read_result.headers['apim-request-id'] }, 200, res_headers) if request.method == 'GET' : # Set CORS headers for main requests res_headers = { 'Access-Control-Allow-Origin': 'https://yizm.work' } oid = request.args.get('operationId') get_url = ''.join([get_endpoint, oid]) get_headers = { 'Ocp-Apim-Subscription-Key': subscription_key, 'Content-Type': 'application/json' } read_result = requests.get(get_url, headers=get_headers) return (read_result.json(), 200, res_headers)
?ハマッたポイント
REST APIにPOSTして、「apim-request-id」が返却されるトコ。
これ、ヘッダー情報で「apim-request-id」が返ってくるんですよ?
Responceボディが空っぽで、最初ちゃんとリクエスト通ってるのか理解できなくて、ん?ん?ん?って何度もリクエスト投げちゃいました?
?これは、まだプレビュー版のデモです。
この検証結果だけを見て、Googleの方がよさそーかな?ってなるのはまだ早いかもしれません。
v3.2のGAが楽しみですね?