#daiizメモ

Scrapboxに夢中

Google Cloud Vision API をすばやく試す

Cloud Vision APIのLABEL_DETECTIONでは,画像データをPOST送信するだけで,その画像の中に何が写っているかを瞬時に返してくれる. https://cloud.google.com/vision/?hl=ja

料金表の説明も書いてあるが,一ヶ月あたり1000リクエストまでは無料なので,一人で実験用に使うくらいなら気にしなくても大丈夫だと思うので使ってみた.実際に試してみると分かるが,ものすごく的確な結果がすばやく返ってくる.かなり興奮した.

f:id:daiiz:20160309005235p:plain:h56

ということで,実際にAPIを呼び出して感動するまでの手順を完璧にまとめておく.本記事内で紹介するソースコードとかはコピペすれば動くはずなので,是非実際に好きな写真を与えて実行してみてほしい.

APIキーを取得する

最初のステップは,APIキーを取得する作業.こちらの記事: がとてもわかりやすかった.

途中でAPIキーの種類を選ぶシーンがあり,上記記事では「ブラウザ キー」を選択しているが,本記事ではローカルサーバーからAPIを呼ぶので「サーバー キー」を選択してください.以降の説明ではここで取得したキーをAPI_KEYと書きます.

ローカルサーバのプログラムを書く

ローカルサーバーのプログラムをPython 2.7で書きます.後述しますが,APIに写真を与えるために自作ツールtfPhotoPaletteを使いました.このツールでは,画像の任意部分を切り抜いたり,サイズを縮小したりできます.

今回書くローカルサーバー側のプログラムは,簡単に書くと以下のように,

  • tfPhotoPaletteから画像を受け取って,
  • 受け取った画像をCloud Vision APIにセットしてリクエスト送信する.
  • Cloud Vision APIから返却されたJSONデータをtfPhotoPaletteに返す

ような処理を担います.この一連の流れが完了すると,tfPhotoPaletteにはラベリングされた結果が表示されます.

f:id:daiiz:20160326013354p:plain:w450

まずは,必要なモジュールを以下のようにpipインストールします.

$ pip install flask
$ pip install requests

続いて,以下のPythonプログラムを適当な名前(例えばpalette_server.py)で保存します.関数goog_cloud_vison内の一行目のAPI_KEYの部分は先ほど取得したAPIサーバー キーで置き換えてください.*1

# coding: utf-8
from flask import Flask, request, jsonify
import urllib
import base64
import json
import requests

app = Flask(__name__)
default_port = 52892

GOOGLE_CLOUD_VISION_API_URL = 'https://vision.googleapis.com/v1/images:annotate?key='

def goog_cloud_vison (image_content):
    api_url = GOOGLE_CLOUD_VISION_API_URL + API_KEY
    req_body = json.dumps({
        'requests': [{
            'image': {
                'content': image_content
            },
            'features': [{
                'type': 'LABEL_DETECTION',
                'maxResults': 10,
            }]
        }]
    })
    res = requests.post(api_url, data=req_body)
    return res.json()

@app.route('/', methods=['GET'])
def hello ():
    return 'Hello! This is a palette_server.'

@app.route('/api/classify', methods=['POST'])
def classify ():
    # tfPhotoPaletteから受信するJSON形式のリクエスト
    tfpp_json = request.json
    if ('jpg' in tfpp_json):
        image_base64_str = tfpp_json['jpg'].replace('data:image/jpeg;base64,', '')
        img_jpg = image_base64_str.decode('base64')
        image_content = base64.b64encode(img_jpg)
        # Label Detection: Google Cloud Vision で物体認識する
        res_json = goog_cloud_vison(image_content)

        # tfPhotoPalette向けの付加情報
        res_json['description'] = 'Label Detection (Google Cloud Vision)'

        return jsonify(res_json)
    else:
        return jsonify(description='Bad request')

app.run(port=default_port)
スポンサーリンク

tfPhotoPaletteを入手して起動

Chrome ウェブストアからインストールできます. インストールが完了すると,chrome://apps/のリスト内にアプリのアイコンが現れるので,それをクリックすると起動できます.

ローカルサーバを起動

$ python palette_server.py

写真を与えて,Label Detection!

https://i.gyazo.com/1484dd1d17d3261f550b695f2e8d3a2f.gif


ウィンドウ右下の「Play」ボタンをクリックすると小窓が開きます.左上のセレクトボックスを「Original photo」や「Cropped photo」に設定して,その隣の「Classify」ボタンをクリックします.これでローカルサーバに画像が送信されます.

ローカルサーバは受け取った画像データをセットして,Cloud Vision APIリクエストを送信します.1秒未満待つと,以下のように,先程の小窓にラベル付けされた結果が表示されます.

https://i.gyazo.com/14f57b3eee0b2f636251a5e9f089984d.png
クリックして拡大


結果をよく見てみると,vegetableが入っているsoupっぽいcurryという状況が完璧に説明されています.驚いた.

f:id:daiiz:20160309005235p:plain:h56

余談

ラベリング結果のJSONに含まれるmidというのは,Freebaseというナレッジグラフ上での固有IDらしい.実際にFreebaseのウェブサイトで検索してみるとcurry/m/0hr1s_wとなっていることが確認できる.*2