Google APIのAccess Tokenを取得してGoogle Cloud MLでオンライン予測のリクエストを投げています。そのときの記録です。TensorFlow Object Detection APIを使って訓練したモデルを使っています。
記事「Google API の Access Token を手動で取得する」を参考にしています。
関連記事
- TensorFlow Object Detection APIをUbuntuにインストール
- Object Detection APIを使って堀川君を検知
- Object Detection APIのsaved_model出力
- Object Detectionのためのアノテーション(ラベリング)
前提
Google APIが有効化済
手順
1. GCPでOAuthクライアントID作成
Google Cloud Consoleの認証ページにブラウザでアクセスします。
「認証情報を作成」から「OAuthクライアントID」を選択。
OAuthクライアントIDのJSONファイルをダウンロード。
JSONファイルの中身。
{
"installed": {
"client_id": "<client_id>.apps.googleusercontent.com",
"project_id": "cloud-ml01",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_secret": "<client_secret>",
"redirect_uris": [
"urn:ietf:wg:oauth:2.0:oob",
"http://localhost"
]
}
}
2. Authorization Code取得
client_idのパラメータを1で取得した値を設定してブラウザで下記のURLでアクセス。
※Cloud Machine Learning Engineのスコープ
https://accounts.google.com/o/oauth2/auth?client_id=xxx&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/cloud-platform&response_type=code&approval_prompt=force&access_type=offline
認証を求められるので、「許可」を選択。画面でAuthorization Codeをコピーして取得。
3. Access Token取得
今度はcurlを使ってAccess Tokenを取得。client_idとclient_secret、redirect_uriはjsonにある値を設定。codeは2で取得したAuthorization Codeを設定。
curl -k -d client_id=xxx -d client_secret=xxx -d redirect_uri=xxx -d grant_type=authorization_code -d code=xxxxx https://accounts.google.com/o/oauth2/token
JSON形式でAccess Token取得。
{
"access_token": "xxx",
"expires_in": 3600,
"refresh_token": "xxx",
"scope": "https://www.googleapis.com/auth/cloud-platform",
"token_type": "Bearer"
}
4. Httpのテスト(Postman)
Postmanを使ってHttpでのリクエストテストをします。
ヘッダのAuthorizationにBearerに続いてAccess Tokenを貼り付けます(BearerとAccess Tokenの間にスペースが必要)。
- http method: POST
- URL: https://ml.googleapis.com/v1/projects/project_name/models/model_name:predict
- Headers:
- Content-Type: application/json
- Authorization: Bearer AccessToken_xxxx
- Body:下記json形式のrawデータ
{
"instances": [
{
"inputs":[[[numpy形式]]]
}
]
}
ちなみに画像のnumpy形式を出力するために以下のpythonプログラムを作成。どうしてもデータ量が重くなるので、10kb程度の画像を使っています。pillowとnumpyをインストールしたpython3.5.6環境で実行しています。
from PIL import Image
import numpy as np
import json
def load_image_into_numpy_array(image):
(im_width, im_height) = image.size
return np.array(image.getdata()).reshape(
(im_height, im_width, 3)).astype(np.uint8)
image = Image.open(r'C:\tmp\tensorflow\od\horikawa\test01.jpg')
image_np = load_image_into_numpy_array(image)
print(image_np.shape)
b = image_np.tolist()
json_file = r"C:\tmp\image.json"
with open(json_file, 'w', encoding='utf-8') as f:
instance = {"instances":[{ "inputs": b} ]}
json.dump(instance, f , sort_keys=True)
f.write("\n")
print(json.dumps(instance))
おまけ
Google公式のサンプルを参考にpythonでhttpを投げるとこんな感じです。コードが汚くてすいません。前提として「認証情報設定」に従ってサービスアカウントを作成して秘密鍵をjosn形式でダウンロードしておく必要があります。
import base64, json, httplib2, six, googleapiclient.discovery
from oauth2client.service_account import ServiceAccountCredentials
from googleapiclient import errors
from PIL import Image
import numpy as np
def load_image_into_numpy_array(image):
(im_width, im_height) = image.size
return np.array(image.getdata()).reshape(
(im_height, im_width, 3)).astype(np.uint8)
# [START predict_json]
def predict_json():
"""Send json data to a deployed model for prediction.
Args:
project (str): project where the Cloud ML Engine Model is deployed.
model (str): model name.
instances ([Mapping[str: Any]]): Keys should be the names of Tensors
your deployed model expects as inputs. Values should be datatypes
convertible to Tensors, or (potentially nested) lists of datatypes
convertible to tensors.
version: str, version of the model to target.
Returns:
Mapping[str: any]: dictionary of prediction results defined by the
model.
"""
# Create the ML Engine service object.
# To authenticate set the environment variable
# GOOGLE_APPLICATION_CREDENTIALS=<path_to_service_account_file>
SCOPES = ['https://www.googleapis.com/auth/cloud-platform']
# API & Services -> Credentials -> Create Credential -> service account key
# Set json file
SERVICE_ACCOUNT_FILE = r'C:\xxxx.json'
credentials = ServiceAccountCredentials.from_json_keyfile_name(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
# Need to set timeout, since prediction takes time
http = httplib2.Http(timeout=2000)
http = credentials.authorize(http)
service = googleapiclient.discovery.build('ml', 'v1', http=http)
#use default version, change project name and model name
name = 'projects/{}/models/{}'.format('project name', 'model name')
image = Image.open(r'C:\test01.jpg')
print(image)
image_np = load_image_into_numpy_array(image)
print(image_np.shape)
image_list = image_np.tolist()
print('predict start:'+ name)
response = service.projects().predict(
name=name,
body={'instances':[ { "inputs": image_list} ]}
).execute()
print('predict end:'+ name)
if 'error' in response:
raise RuntimeError(response['error'])
json_dump_data = json.dumps(response['predictions'])
json_data = json.loads(json_dump_data)
return json_data
def main():
"""Send user input to the prediction service."""
try:
result = predict_json()
except RuntimeError as err:
print(str(err))
return result
if __name__ == '__main__':
result = main( )
print(result)
print(result[0]["detection_scores"][0])
print(result[0]["num_detections"])
print(result[0]["detection_boxes"][0])
print(result[0]["detection_classes"][0])