Google Cloud Vision APIを使ってみた

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Google Cloud Vision APIとは

Google Cloud Vision APIは、Google Cloud Platform(GCP)が提供する機械学習サービスの一種です。

このサービスを利用することで、Googleの持つ画像に関する機械学習モデルを使い、対象となる画像から様々な情報を取得することができます。

取得できる情報の例として、以下のものがあります。

  • 猫やヨットなど、画像に含まれている物体の検知
  • 画像内に含まれている文章やロゴの取得
  • 人物の顔認識やその表情が示す感情に関する情報の取得
  • コンテンツがアダルト、暴力的など不適切な要素を持つかの判定

本記事では、Google Cloud Vision APIを使って取得できる情報の種類や利用法についてまとめます。

機能概要

Cloud Vision APIでは、問い合わせ時に機能を指定することで、以下の様々な情報を画像から取得することができます。

Feature Type Description
LABEL_DETECTION 画像内に写っている物体の検知、分類
TEXT_DETECTION 画像中の文章の抽出(OCR機能)
FACE_DETECTION 画像に写っている顔情報、表情などの情報の検知
LANDMARK_DETECTION 画像中の構造物などから、名所の検知
LOGO_DETECTION 画像に含まれる有名なロゴの検知
SAFE_SEARCH_DETECTION 画像に有害なコンテンツが含まれているかの判別
IMAGE_PROPERTIES 画像に関する情報(色情報など)を取得

使い方

Google Cloud Vision APIを利用する場合、直接REST APIに問い合わせを行う方法と、Google Cloud SDKを通して問い合わせを行う方法の2つがあります。今回はPython用のSDKを用いて問い合わせを行っています。

問い合わせ用のスクリプトは、サンプルを改変したものを用いています。

注意点として、事前に認証情報をSDKに登録する必要があります

import argparse
import base64
import httplib2

from pprint import pprint

from googleapiclient import discovery
from oauth2client.client import GoogleCredentials

DISCOVERY_URL='https://{api}.googleapis.com/$discovery/rest?version={apiVersion}'

def main(photo_file):
    """Run a label request on a single image"""

    credentials = GoogleCredentials.get_application_default()
    service = discovery.build('vision', 'v1', credentials=credentials,
                              discoveryServiceUrl=DISCOVERY_URL)

    with open(photo_file, 'rb') as image:
        image_content = base64.b64encode(image.read())
        service_request = service.images().annotate(body={
            'requests': [{
                'image': {
                    'content': image_content.decode('UTF-8')
                },
                'features': [{
                    'type': 'LABEL_DETECTION',
                    'maxResults': 10
                }]
            }]
        })

        response = service_request.execute()
        pprint(response)
        return 0

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('image_file', help='The image you\'d like to label.')
    args = parser.parse_args()
    main(args.image_file)

機能を変更したい場合は、'type' : 'LABEL_DETECTION'の部分を対応するfeature_typeに変更します。

使ってみた

試しにいくつかの機能を使い、どのような結果が返ってくるのかを確認してみました。

物体検知 (LABEL_DETECTION)

LABEL_DETECTIONでは、画像に写っている物体などを検知し、ラベルとして情報を返します。各ラベルは以下の項目をもち、この情報からラベルの確度を知ることができます。

項目名 内容
description ラベルの名称
mid Google Knowledge Graphなどで使われるラベルのID
score ラベルの確度

試しに以下の写真をAPIに渡すと、その写真に関する情報がラベルとして返却されていることがわかります。

mowe

$ python label.py ../test_image/mowe.JPG
{u'responses': [{u'labelAnnotations': [{u'description': u'vehicle',
                                        u'mid': u'/m/07yv9',
                                        u'score': 0.81806344},
                                       {u'description': u'glider',
                                        u'mid': u'/m/05256q_',
                                        u'score': 0.7572208},
                                       {u'description': u'glider',
                                        u'mid': u'/m/05h5q_s',
                                        u'score': 0.69410884},
                                       {u'description': u'flight',
                                        u'mid': u'/m/01515d',
                                        u'score': 0.67155361},
                                       {u'description': u'gliding',
                                        u'mid': u'/m/039r_',
                                        u'score': 0.66025084},
                                       {u'description': u'toy',
                                        u'mid': u'/m/0138tl',
                                        u'score': 0.52656513}]}]}

次の例では寿司の写真を渡してみましたが、「食物」、「皿」などの情報は得られましたが、肝心の「寿司」「サーモン」などの情報は得ることができませんでした。

salmon_sushi

$ python label.py ../test_image/salmon_sushi.JPG
{u'responses': [{u'labelAnnotations': [{u'description': u'produce',
                                        u'mid': u'/m/036qh8',
                                        u'score': 0.86890507},
                                       {u'description': u'dish',
                                        u'mid': u'/m/02q08p0',
                                        u'score': 0.77188647},
                                       {u'description': u'food',
                                        u'mid': u'/m/02wbm',
                                        u'score': 0.69438821},
                                       {u'description': u'vegetable',
                                        u'mid': u'/m/0f4s2w',
                                        u'score': 0.64845425},
                                       {u'description': u'meal',
                                        u'mid': u'/m/0krfg',
                                        u'score': 0.64001364}]}]}

当然ながら写っているものを100%検出できるわけではないので、対象となる物体に対してどの程度期待ができるかは、しばらく使ってみて確認する必要があります。

ランドマーク検知 (LANDMARK_DETECTION)

LANDMARK_DETECTIONでは、写真に含まれた建造物や地形などから、撮影を行った観光地や名所の検知をおこない、その情報を返します。

項目名 内容
boundingPoly 対象の画像内での位置
description ランドマークの名称
location 位置情報
mid Google Knowledge Graphなどで使われるラベルのID
score ランドマークの確度

ランドマークのテストに自由の女神像を渡してみました。

statue_of_liberty

$ python label.py ../test_image/statue_of_liberty.jpeg
{u'responses': [{u'landmarkAnnotations': [{u'boundingPoly': {u'vertices': [{u'x': 422,
                                                                            u'y': 170},
                                                                           {u'x': 578,
                                                                            u'y': 170},
                                                                            ...
                                           u'description': u'Statue of Liberty',
                                           u'locations': [{u'latLng': {u'latitude': 35.62777376266495,
                                                                       u'longitude': 139.77187}}],
                                           u'mid': u'/m/026vw4',
                                           u'score': 0.34943753}]}]}

ランドマークに関する情報として、名前やlat,lngの位置情報が得られることがわかります。

次に東京駅の画像を与えてみましたが、ランドマークとしては検知されませんでした。

tokyo_station

$ python label.py ../test_image/tokyo_station.jpg
{u'responses': [{}]}

顔認識 (FACE_DETECTION)

FACE_DETECTIONは、画像に含まれている人物の顔を検知し、その位置や表情、帽子をかぶっているかなどの情報を返します。

項目名 内容
boundingPoly 検出された顔のおおまかな位置情報
fdBoundingPoly boundingPolyよりも厳密な範囲での顔の位置情報
landmarks[] 顔の特徴点(目や口など)の情報
rollAngle 顔の傾き(ロール角)
panAngle 顔の傾き(ヨー角)
tiltAngle 顔の傾き(ピッチ角)
detectionConfidence 検知された顔の確度
landmarkingConfidence 顔の特徴点についての確度
joyLikelihood 楽しい表情であるか
sorrowLikelihood 悲しい表情であるか
angerLikelihood 怒りの表情であるか
surpriseLikelihood 驚きの表情であるか
underExposedLikelihood 露光不足であるか
blurredLikelihood ぼやけているか
headwearLikelihood 帽子をかぶっているか

試しに自分の写真を与えてみました。

hiratakei

$ python label.py ../test_image/hiratakei.jpg
{u'responses': [{u'faceAnnotations': [{u'angerLikelihood': u'VERY_UNLIKELY',
                                       u'blurredLikelihood': u'VERY_UNLIKELY',
                                       u'boundingPoly': {u'vertices': [{u'x': 20,
                                                                        u'y': 22},
                                                                        ...
                                       u'detectionConfidence': 0.94021934,
                                       u'fdBoundingPoly': {u'vertices': [{u'x': 47,
                                                                          u'y': 79},
                                                                          ...
                                       u'headwearLikelihood': u'VERY_UNLIKELY',
                                       u'joyLikelihood': u'VERY_UNLIKELY',
                                       u'landmarkingConfidence': 0.5052399,
                                       u'landmarks': [{u'position': {u'x': 77.909637,
                                                                     u'y': 115.49197,
                                                                     u'z': -0.000415676},
                                                       u'type': u'LEFT_EYE'},
                                                       ...
                                       u'panAngle': 4.4744964,
                                       u'rollAngle': -4.6160045,
                                       u'sorrowLikelihood': u'VERY_UNLIKELY',
                                       u'surpriseLikelihood': u'VERY_UNLIKELY',
                                       u'tiltAngle': -10.989608,
                                       u'underExposedLikelihood': u'VERY_UNLIKELY'}]}]}

見事に無表情だと判定されています。そのほか、すこしうつむき気味になっていることなどが顔の角度情報からわかります。

弊社の二次元社員でもためしてみました。

mesoko_01

$ python label.py ../test_image/mesoko_01.png
{u'responses': [{}]}

二次元では厳しいようです。

価格

Cloud Vision APIの料金は、問い合わせ回数に応じて発生します。

各機能につき、月1000問い合わせまでは無料、以降は回数に応じて問い合わせごとの料金が設定されています。

Feature 1 - 1000 units/month 1001- 1,000,000 units/month 1,000,001 to 5,000,000 units/month 5,000,001 - 20,000,000 units/month
LABEL_DETECTION Free $5.00 $4.00 $2.00
TEXT_DETECTION Free $2.50 $1.50 $0.60
SAFE_SEARCH_DETECTION Free $2.50 $1.50 $0.60
FACE_DETECTION Free $2.50 $1.50 $0.60
LANDMARK_DETECTION Free $2.50 $1.50 $0.60
LOGO_DETECTION Free $2.50 $1.50 $0.60
IMAGE_PROPERTIES Free $2.50 $1.50 $0.60

おわりに

なかなか遊べそうなサービスなので、今後もいろいろ試してみたいと思います。

参考資料