質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.23%

CloudVision apiで得られた認識結果から座標値を取り出したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 208

ookura

score 19

json型で返された結果から読み取り座標値を読み取って対象の画像に四角いマーキングを
したいと思っているのですが座標値の取り方がいまいちわかりません。

不勉強で申し訳ありませんがどなたかご教示いただけますと幸いです。
下記コードとなります。

import requests
import base64
import json

GOOGLE_CLOUD_VISION_API_URL = 'https://vision.googleapis.com/v1/images:annotate?key='
API_KEY = 'AIzaSyA5HPWqOkSZf0AAj9N7Ndg584huXVIy8yc' # 取得したAPIキーを入力してください。

# APIを呼び、認識結果をjson型で返す
def request_cloud_vison_api(image_base64):
    api_url = GOOGLE_CLOUD_VISION_API_URL + API_KEY
    req_body = json.dumps({
        'requests': [{
            'image': {
                'content': image_base64.decode('utf-8') # jsonに変換するためにstring型に変換する
            },
            'features': [{
                'type': 'DOCUMENT_TEXT_DETECTION', # ここを変更することで分析内容を変更できる
                'maxResults': 10,
            }]
        }]
    })
    res = requests.post(api_url, data=req_body)
    return res.json()

# 画像読み込み
def img_to_base64(filepath):
    with open(filepath, 'rb') as img:
        img_byte = img.read()
    return base64.b64encode(img_byte)

# 文字認識させたい画像を./img.pngとする
img_base64 = img_to_base64(r"C:\Users\straw\Desktop\AOCR\OCR\base\ベース20201120.jpg")
result = request_cloud_vison_api(img_base64)

#認識した文字の位置など、すべての情報を出力
#print("{}".format(json.dumps(result, indent=4)))

#認識した文字のみを出力
text_r = result["responses"][0]["fullTextAnnotation"]["text"]
for text in text_r:
    temp2 = [
        result["responses"][0]["fullTextAnnotation"]["text"],
        #座標1の取得
        #座標2の取得
    ]
    print(result["responses"][0]["fullTextAnnotation"]["text"])
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

symbols内のboundingBoxの座標値を取得すればよいかと思います。
参考:AnnotateImageResponse

import json
from PIL import Image, ImageDraw

# https://cloud.google.com/vision/docs/images/sign_small.jpg
img = Image.open('sign_small.jpg')
draw = ImageDraw.Draw(img)

# response
with open('res.json') as f:
    res = json.load(f)

res = res['responses'][0]['fullTextAnnotation']
#text = res['text']
pages = res['pages']
for page in pages:
    blocks = page['blocks']
    for block in blocks:
        paras = block['paragraphs']
        for para in paras:
            words = para['words']
            for word in words:
                symbols = word['symbols']
                for symbol in symbols:
                    print('-----')
                    print(symbol['text'])
                    vs = symbol['boundingBox']['vertices']
                    ps = []
                    for v in vs:
                        x, y = v['x'], v['y']
                        ps.append((x,y))
                        print(x,y)
                    draw.polygon(ps, outline=(255,0,0))


img.save('ret.png')

Request body

{
  "requests": [
    {
      "image": {
        "source": {
          "imageUri": "https://cloud.google.com/vision/docs/images/sign_small.jpg"
        }
      },
      "features": [
        {
          "type": "DOCUMENT_TEXT_DETECTION"
        }
      ]
    }
  ]
}


元画像が小さいためか、YOUR ENGINEあたりの矩形がちょっとあやしいですが。
イメージ説明

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/11/29 20:01

    ご回答ありがとうございます。
    座標値の抜きだしができました。
    しかし、抜き出した座標値が単語ブロックごとではなく1文字毎になってしまうのですが、
    (DOCUMENT_TEXT_DETECTIONで設定しているのにかかわらず)
    単語ブロック毎に単語と座標値を抜き出すには、
    抜き出した内容を連結するのが常套手段でしょうか?
    または、そのまま単語ブロックでその座標値を抜き出す方法があるのでしょうか。
    お手数ですが合わせてご教示いただけますと幸いです。

    キャンセル

  • 2020/11/29 20:05

    「単語ブロック」がレスポンス内のどれを指すのかが分かりませんので何とも言えません。
    参考URLにレスポンスの詳細がありますので、その中から該当しそうな座標値をご自身で探してみてください。

    キャンセル

  • 2020/11/29 22:12

    申し訳ありません。参考URLで調べてみたのですがよくわからなく、できれば再度ご教示ください。
    TextAnnotationのFieldsの内のtextを取得した場合、(コード中のresult["responses"][0]["fullTextAnnotation"]["text"]の部分)であれば、例えば,掲載いただいたsign_small.jpgのWAITING?の部分が1文字ずつではなく単語で取得ができました。
    単語で取得した際の座標値を取得したかったのですが、ご教示いただいたコード、参考URL内の内容を見ると1文字ずつの座標値の取得でしたのでよい方法はないかなと思っています。
    何度も申し訳ありませんがご教示いただけますと幸いです。

    キャンセル

  • 2020/11/30 00:02

    自己解決しました。
    fullTextAnnotationではなくtextAnnotationsから探っていくと単語単位とその座標値が取れました
    ご丁寧にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.23%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る