Cloud Vision APIを使ってみた

# はじめに

隣の席の先輩が先日、`Cloud Auto ML Vision`を用いてカレイの識別を試みました。
→　[Cloud AutoML Visionを使ってカレイの種類を識別してみた](https://medium.com/google-cloud-jp/cloud-automl-vision%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%82%AB%E3%83%AC%E3%82%A4%E3%81%AE%E7%A8%AE%E9%A1%9E%E3%82%92%E8%AD%98%E5%88%A5%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F-5a1cb2379e29)
この記事で思ったよりも簡単に画像識別が出来るのを見て、それならばと、とりあえず入門編としてまずは`Cloud Vision API`を触ってみようと今回チャレンジしました。

# Cloud Vision APIとは

Cloud Vision APIとは、Googleが用意した学習モデルを利用して、画像から様々な情報を抽出することができるサービスです。
下記の様に様々な機能があります。

|機能のタイプ|説明|
|:---|:----|
|ラベル検出|乗り物や動物など、画像に写っているさまざまなカテゴリの物体を検出|
|テキスト検出|画像内のテキストに対して光学式文字認識（OCR）を実行し、テキストを検出|
|ドキュメントテキスト検出|ドキュメントなどの高密度テキスト画像に対してOCRを実行し、ドキュメントテキストを検出|
|セーフサーチプロパティの検出|アダルト コンテンツや暴力的コンテンツなど、画像に含まれる不適切なコンテンツを検出|
|顔検出|画像に含まれる複数の人物の顔を検出（ただし、個人を特定する顔認識には対応していません。）|
|ランドマーク検出|画像内の地理的ランドマークを検出|
|ロゴ検出|画像内の企業ロゴを検出|
|画像プロパティの検出|画像の一連のプロパティ（画像のドミナント カラーなど）を検出|
|ウェブ検出|画像内のニュース、イベント、有名人などの時事的なエンティティを検出し、Google画像検索の機能を使用してウェブ上で同様の画像を検索|
|クロップヒントの検出|画像上のクロップ領域の推奨頂点を調べる|
|複数のオブジェクトの検出[ベータ版]|画像に含まれている複数のオブジェクトを検出し、抽出|

今回はこの中から、「ラベル検出」「テキスト検出」「ランドマーク検出」を試してみたいと思います。

# 事前準備

`Cloud Vision API`はGCPのサービスなので、事前に下記手順が必要です。

- GCPのプロジェクト作成
- プロジェクトに対して課金を有効にする
- Cloud Vision API を有効にする
- サービスアカウントの作成・使用

こちらの詳細は公式を参照ください。
[Vision API を有効にする](https://cloud.google.com/vision/docs/before-you-begin?hl=ja)
[Cloud Vision API に対する認証](https://cloud.google.com/vision/docs/auth?hl=ja)


# ラベル検出

まずはラベル検出。下記のコードで、画像から乗り物や動物などさまざまなラベルを検出できます。

```python:label_detection.py
import io
from google.cloud import vision

client = vision.ImageAnnotatorClient()
with io.open('path/to/image', 'rb') as image_file:
    content = image_file.read()
image = vision.types.Image(content=content)

response = client.label_detection(image=image)
labels = response.label_annotations

for label in labels:
    print(label.description)
```

|画像|検出されたラベル|
|:---|:---|
|![label01.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/423ea103-84e1-5283-555e-df4293b933e5.jpeg)|cat, whiskers, skin, small to medium sized cats, nose, eye, cat like mammal, fauna, close up, snou|
|![label02.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/9acc338e-c77d-afe5-0ba3-0c4db2351a44.jpeg)|cup, coffee cup, coffee, serveware, tableware, cup, espresso, caffeine, ristretto, sauce|
|![label03.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/1d453692-13e4-45f4-881e-01b0a7af770e.jpeg)|jeans, shoe, trousers, vehicle, bag, asphalt, product|

信頼度が高い順にラベルが並べられますが、モチーフがはっきりとした画像なら精度はかなり良さそうです。

# テキスト検出

次にテキスト検出。画像から文字列全体、個々の単語、それらの境界ボックスを検出できます。
ちなみにコードの上半分は先程のラベル検出と一緒です。

```python:text_detection.py
import io
from google.cloud import vision

client = vision.ImageAnnotatorClient()
with io.open('path/to/image', 'rb') as image_file:
    content = image_file.read()
image = vision.types.Image(content=content)

response = client.text_detection(image=image)
texts = response.text_annotations

for text in texts:
    print('\n"{}"'.format(text.description))
    vertices = (['({},{})'.format(vertex.x, vertex.y)
                 for vertex in text.bounding_poly.vertices])
    print('bounds: {}'.format(','.join(vertices)))
```

|画像|検出されたフレーズ / その境界ボックス<br>(および個々の単語とその境界ボックス) |
|:---|:---|
|![text_detection01.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/32c048b6-2a83-ac0e-f058-ef4fc9e7edae.jpeg)|"check!!<br>"<br>bounds: (38,17),(193,17),(193,133),(38,133)<br><br>"check!!"<br>bounds: (38,102),(174,17),(193,49),(58,133)|
|![text_detection02.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/c319b22c-9575-1eaf-2520-9582b07be4ba.jpeg)|"No!<br>"<br>bounds: (194,51),(283,51),(283,99),(194,99)<br><br>"No!"<br>bounds: (196,51),(283,55),(281,99),(194,95)|
|![text_detection03.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/295d23f7-5ccf-709f-544f-2dffeb2e0823.jpeg)|"Thank You<br>"<br>bounds: (77,100),(266,100),(266,138),(77,138)<br><br>"Thank"<br>bounds: (78,100),(185,102),(184,137),(77,135)<br><br>"You"<br>bounds: (200,105),(266,106),(265,138),(199,137)|

こちらも斜め向いた文字や、手書き文字を含んでいるのに見事に文字を検出できました。

# ランドマーク検出

最後にランドマーク検出。画像からランドマークの名前と場所を検出できます。
こちらもコードの上半分はラベル検出・テキスト検出と一緒です。

```python:landmark_detection.py
import io
from google.cloud import vision

client = vision.ImageAnnotatorClient()
with io.open('path/to/image', 'rb') as image_file:
    content = image_file.read()
image = vision.types.Image(content=content)

response = client.landmark_detection(image=image)
landmarks = response.landmark_annotations

for landmark in landmarks:
    print(landmark.description)
    for location in landmark.locations:
        lat_lng = location.lat_lng
        print('Latitude {}'.format(lat_lng.latitude))
        print('Longitude {}'.format(lat_lng.longitude))
```

|画像|ランドマークの名前と場所|
|:---|:---|
|![landmark01.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/e1e84ecd-a281-2c77-51c6-4dced2885e12.jpeg)|Arc de Triomphe<br>Latitude 48.873667<br>Longitude 2.295134|
|![landmark02.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/cd0edd86-e02e-662d-e473-20775b80b5a7.jpeg)|Sagrada Familia ("Expiatory Temple of the Holy Family")<br>Latitude 41.403579<br>Longitude 2.174242|
|![landmark03.jpg](https://qiita-image-store.s3.amazonaws.com/0/91904/764c1d9b-8809-f5ba-0898-ca408648462c.jpeg)| |

1つ目の「凱旋門」、2つ目の「サグラダ・ファミリア」はバッチリ検出できました。

3つ目は判別できなかったのか、レスポンスが空でした。
ドバイにある世界一高いビル「ブルジュ・ハリファ」でしたが、写真がわかりづらかったのかもですね...


# 感想

コード自体はほぼサンプルの流用でしたが、当初思ってた以上にお手軽に試せました。
Googleが事前に学習したモデルを使えるというのも、本当にありがたいです。

他にも面白そうな機能が有ったので、また別の機会に試してみたいと思います！

# 参考

- [公式ドキュメント](https://cloud.google.com/vision/docs/?hl=ja)
- [ラベル検出の公式サンプル](https://cloud.google.com/vision/docs/detecting-labels?hl=ja)
- [テキスト検出の公式サンプル](https://cloud.google.com/vision/docs/detecting-text?hl=ja)
- [ランドマーク検出の公式サンプル](https://cloud.google.com/vision/docs/detecting-landmarks?hl=ja)
- [Cloud Vision APIで画像解析](https://qiita.com/rei-gouzo/items/317f552531311f2ec3e6)
- [Google Cloud Vision API（画像解析）を30分で試す](https://qiita.com/t-fujiwara/items/7e1f7c52a73887519ac1)
- [Google Cloud Vision APIを使ってみた](https://dev.classmethod.jp/cloud/gcp/google-cloud-vision-api-get-start/)