概要
PythonからCloud Vision APIを呼び出して画像やPDFから文字を読む。
バージョン情報
- Python 3.7.4
- google-cloud-vision==0.40.0
インストール
pip install google-cloud-vision
Cloud Visionでできること
下記のようなことができる。なかなか多彩。
- CROP_HINTS - 画像切り抜きのヒント
- DOCUMENT_TEXT_DETECTION - OCRでドキュメント解析
- FACE_DETECTION - 顔検出
- IMAGE_PROPERTIES - 画像のカラー情報とか
- LABEL_DETECTION - 画像に写っているものをラベル付け
- LANDMARK_DETECTION - ランドマーク検出
- LOGO_DETECTION - ロゴの検出
- OBJECT_LOCALIZATION - 物体の検出
- PRODUCT_SEARCH - 画像に類似する商品の検索
- SAFE_SEARCH_DETECTION - アダルトや暴力的なシーン等の検出
- TEXT_DETECTION - OCRテキスト検出
- WEB_DETECTION - Webページの解析
サンプルデータ
本例では下記のような画像(pngとpdfの2種類を用意)を解析させる。
サービスアカウントの作成
本例では認証はサービスアカウントを作成して落としたjsonファイルを利用して行う。
Cloud Vision自体のRoleは特に設定する必要がないらしいので、連携させて使うことが多いCloud Storageの権限だけ持たせて鍵を作る。
Web UIの「IAM & Admin」から「Service Account」を選んで「Create Service Account」で下記のような感じで入力。
次のページで適当に「Storage Admin」あたりを入れておいて次のページへ移動。
CREATE KEYで鍵をjsonファイルを作成してDONE。
落としたjsonファイルは仮にexample.jsonという名前にしてサンプルコードを動かす直下に置いておくこと。
画像ファイルからOCR
DOCUMENT_TEXT_DETECTIONを使うと画像形式のドキュメントからテキストを取得できる。
上述のサンプルデータ(example.png)を解析させてみる。
from google.cloud import vision # service accountのjsonからclientの生成 client = vision.ImageAnnotatorClient.from_service_account_json( 'example.json') # 対象画像の読み込み with open('example.png', 'rb') as fp: content = fp.read() image = vision.types.Image(content=content) # APIに投げる response = client.document_text_detection(image=image) document = response.full_text_annotation # テキストの取得 document.text #=> 'Sheet1\nCanis lupus familiaris\n2歳くらい\n雑種(柴系?)\nかわいい\nとてもかわいい\n目に入れても痛くない\nいや、痛い\n'
こんな感じで画像からテキストを取得できる。
APIが有効になっていないと下記のようなエラーが出る。表示されたURLに行って有効にしておく。
PermissionDenied: 403 Cloud Vision API has not been used in project xxxxxxxxxxxx before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/vision.googleapis.com/overview?project=xxxxxxxxxxxx then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.
テキストは単語や文字ごとに座標も格納されている。下記は単語ごとに座標を取った例。
for page in document.pages: for block in page.blocks: for paragraph in block.paragraphs: for word in paragraph.words: box = [(v.x, v.y) for v in word.bounding_box.vertices] text = [] for symbol in word.symbols: text.append(symbol.text) print(box, ''.join(text))
実行結果
[(517, 1), (589, 1), (589, 32), (517, 32)] Sheet1 [(281, 56), (337, 56), (337, 77), (281, 77)] Canis [(350, 56), (407, 56), (407, 77), (350, 77)] lupus [(416, 56), (508, 56), (508, 77), (416, 77)] familiaris [(276, 85), (374, 85), (374, 108), (276, 108)] 2歳くらい [(284, 118), (319, 118), (319, 142), (284, 142)] 雑種 [(331, 118), (337, 118), (337, 142), (331, 142)] ( [(342, 118), (386, 118), (386, 142), (342, 142)] 柴系 [(396, 118), (402, 118), (402, 142), (396, 142)] ? [(408, 118), (414, 118), (414, 142), (408, 142)] ) [(281, 150), (370, 150), (370, 171), (281, 171)] かわいい [(280, 180), (429, 180), (429, 206), (280, 206)] とてもかわいい [(274, 212), (499, 212), (499, 234), (274, 234)] 目に入れても痛くない [(284, 242), (320, 242), (320, 267), (284, 267)] いや [(325, 242), (331, 242), (331, 267), (325, 267)] 、 [(336, 242), (382, 242), (382, 267), (336, 267)] 痛い
PDFファイルからOCR
上述サンプルデータのPDF版(example.pdf)を解析させてみる。
from google.cloud import vision client = vision.ImageAnnotatorClient.from_service_account_json( 'example.json') # DOCUMENT_TEXT_DETECTIONを指定 feature = vision.types.Feature( type=vision.enums.Feature.Type.DOCUMENT_TEXT_DETECTION) # 入力 with open('example.pdf', 'rb') as fp: content = fp.read() input_config = vision.types.InputConfig( content=content, mime_type='application/pdf') # リクエスト req = vision.types.AnnotateFileRequest( features=[feature], input_config=input_config) res = client.batch_annotate_files(requests=[req]) # 1つ目のレスポンスの内容を取得(requestsを1個しか送ってないのでresponseは1つのみ) first_res = res.responses[0]
取れた中身を確認してみる。
# ページ数 first_res.total_pages #=> 1 # DOCUMENT_TEXT_DETECTIONではfull_text_annotationが返ってくる annotation = first_res.responses[0].full_text_annotation # 抽出されたテキスト annotation.text #=> 'Sheet1\nCanis lupus familiaris\n2歳くらい\n雑種(柴系?)\nかわいい\nとてもかわいい\n目に入れても痛くない\nいや、痛い\nページ1\n'
非同期実行してtimeoutも指定したい場合は下記参照。
https://cloud.google.com/vision/docs/pdf
試しにparagraphごとのテキストを抽出してみる。
# テキストをparagraphごとに抽出してみる for page in annotation.pages: for block in page.blocks: for paragraph in block.paragraphs: paragraph_text = [] for word in paragraph.words: for symbol in word.symbols: paragraph_text.append(symbol.text) print(''.join(paragraph_text)) #=> Sheet1Canislupusfamiliaris2歳くらい雑種(柴系?)かわいいとてもかわいい目に入れても痛くないいや、痛い #=> ページ1
今回の画像では上部のテキストとフッタのテキストの2つにparagraphが分割されるようだ。
paragraphの座標を取ってみる。
for vert in paragraph.bounding_box.vertices: print(vert.x, vert.y) #=> 796 2180 #=> 896 2180 #=> 896 2212 #=> 796 2212
改定履歴
Author: Masato Watanabe, Date: 2019-12-07, 記事投稿