画像などの中から物体を検出することを物体認識と言います。
今回は IBM Watson Developer Cloud の提供するサービスの一つ Visual Recognition を用いて、物体認識を行います。
※ IBM Bluemixの登録済みである必要があります。
API用のユーザ名とパスワードを取得
Visual Recognition の Web APIを使うためのユーザ名とパスワードを取得する必要があります。
IBM Bluemixの管理画面からアプリケーションを作成し、そのアプリケーションにサービスを追加する形でVisual Recognitionを追加します。
追加したのち、そのサービスの "資格情報の表示" をクリックするとユーザ名とパスワードが記載されています。
ラベルを取得する
物体認識の結果はラベルとラベルのスコアが組みで返されます。
その際に使用されるラベルを取得します。
# ! /usr/bin/env python
# -*- coding: utf-8 -*-
"""IBM Watson Developer Cloud の Visual Recognitionでラベル情報を取得
"""
import sys
import json
import requests
from pit import Pit
setting = Pit.get('iwdcat',
{'require': {'username': '',
'password': '',
}})
auth_token = setting['username'], setting['password']
url = 'https://gateway.watsonplatform.net/visual-recognition-beta/api/v1/tag/labels'
res = requests.get(url, auth=auth_token, headers={'content-type': 'application/json'})
if res.status_code == requests.codes.ok:
labels = json.loads(res.text)
print('label groups({}): {}'.format(len(labels['label_groups']), labels['label_groups']))
print()
print('labels({}): {}'.format(len(labels['labels']), labels['labels']))
else: # error
print('stauts_code: {} (reason: {})'.format(res.status_code, res.reason))
sys.exit(1)
結果はJSONが返されます。label_groupsはラベルグループのリスト、labelsはラベルのリストです。
画像を解析する
物体認識のAPIには画像をマルチパートで送信する必要があります。
画像はpng, jpgか、zip圧縮されていても良いようです。
以下は1枚のpng画像を送信する例です。
# ! /usr/bin/env python
# -*- coding: utf-8 -*-
"""IBM Watson Developer Cloud の Visual Recognitionで物体認識を行う
"""
import os
import sys
import json
import requests
from pit import Pit
setting = Pit.get('iwdcat',
{'require': {'username': '',
'password': '',
}})
auth_token = setting['username'], setting['password']
url = 'https://gateway.watsonplatform.net/visual-recognition-beta/api/v1/tag/recognize'
filepath = 'var/images/first/2015-04-12-11.47.01.png' # path to image file
filename = os.path.basename(filepath)
res = requests.post(
url, auth=auth_token,
files={
'imgFile': (filename, open(filepath, 'rb')),
}
)
if res.status_code == requests.codes.ok:
data = json.loads(res.text)
for img in data['images']:
print('{} - {}'.format(img['image_id'], img['image_name']))
for label in img['labels']:
print(' {:30}: {}'.format(label['label_name'], label['label_score']))
else: # error
print('stauts_code: {} (reason: {})'.format(res.status_code, res.reason))
sys.exit(1)
1枚の画像を解析します。
出力結果は以下のようになりました。
$ python analyze_image.py
0 - 2015-04-12-11.47.01.png
Outdoors : 0.714211
Nature Scene : 0.671271
Winter Scene : 0.669832
Vertebrate : 0.635903
Boat : 0.61398
Animal : 0.610709
Water Vehicle : 0.607173
Placental Mammal : 0.580503
Snow Scene : 0.571422
Fabric : 0.563129
Gray : 0.56078
Water Sport : 0.555034
Person : 0.533461
Mammal : 0.515725
Surface Water Sport : 0.511447
返却されるデータは次のようなデータです。
{'images': [{'image_id': '0', 'labels': [{'label_score': '0.714211', 'label_name': 'Outdoors'}, {'label_score': '0.671271', 'label_name': 'Nature Scene'}, {'label_score': '0.669832', 'label_name': 'Winter Scene'}, {'label_score': '0.635903', 'label_name': 'Vertebrate'}, {'label_score': '0.61398', 'label_name': 'Boat'}, {'label_score': '0.610709', 'label_name': 'Animal'}, {'label_score': '0.607173', 'label_name': 'Water Vehicle'}, {'label_score': '0.580503', 'label_name': 'Placental Mammal'}, {'label_score': '0.571422', 'label_name': 'Snow Scene'}, {'label_score': '0.563129', 'label_name': 'Fabric'}, {'label_score': '0.56078', 'label_name': 'Gray'}, {'label_score': '0.555034', 'label_name': 'Water Sport'}, {'label_score': '0.533461', 'label_name': 'Person'}, {'label_score': '0.515725', 'label_name': 'Mammal'}, {'label_score': '0.511447', 'label_name': 'Surface Water Sport'}], 'image_name': '2015-04-12-11.47.01.png'}]}
一度のリクエストで複数の画像を送信して一括で解析する
マルチパートで送信するファイルを増やせば、一度のリクエストで複数のファイルを解析にかけることができます。
# ! /usr/bin/env python
# -*- coding: utf-8 -*-
"""IBM Watson Developer Cloud の Visual Recognitionで物体認識を行う
1リクエストに3ファイルを含める
"""
import os
import sys
import json
import requests
from pit import Pit
setting = Pit.get('iwdcat',
{'require': {'username': '',
'password': '',
}})
auth_token = setting['username'], setting['password']
url = 'https://gateway.watsonplatform.net/visual-recognition-beta/api/v1/tag/recognize'
filepaths = [
'var/images/first/2015-04-12-11.47.01.png',
'var/images/first/2015-04-12-11.44.42.png',
'var/images/first/2015-04-12-11.46.11.png',
]
files = dict((os.path.basename(filepath), (os.path.basename(filepath), open(filepath, 'rb'))) for filepath in filepaths)
res = requests.post(
url, auth=auth_token,
files=files,
)
for key, (filename, fp) in files.items():
fp.close()
if res.status_code == requests.codes.ok:
data = json.loads(res.text)
for img in data['images']:
print('{} - {}'.format(img['image_id'], img['image_name']))
for label in img['labels']:
print(' {:30}: {}'.format(label['label_name'], label['label_score']))
else: # error
print('stauts_code: {} (reason: {})'.format(res.status_code, res.reason))
sys.exit(1)
返されるJSONは'images' キーの要素がリストになっており、そこに入力した画像数の要素が入っています。
実行結果は以下のとおりです。
$ python analyze_image_multi.py
0 - 2015-04-12-11.44.42.png
Gray : 0.735805
Winter Scene : 0.7123
Nature Scene : 0.674336
Water Scene : 0.668881
Outdoors : 0.658805
Natural Activity : 0.643865
Vertebrate : 0.603751
Climbing : 0.566247
Animal : 0.537788
Mammal : 0.518001
1 - 2015-04-12-11.46.11.png
Gray : 0.719819
Vertebrate : 0.692607
Animal : 0.690942
Winter Scene : 0.683918
Mammal : 0.669149
Snow Scene : 0.664266
Placental Mammal : 0.663866
Outdoors : 0.66335
Nature Scene : 0.656991
Climbing : 0.645557
Person : 0.557965
Person View : 0.528335
2 - 2015-04-12-11.47.01.png
Outdoors : 0.714211
Nature Scene : 0.671271
Winter Scene : 0.669832
Vertebrate : 0.635903
Boat : 0.61398
Animal : 0.610709
Water Vehicle : 0.607173
Placental Mammal : 0.580503
Snow Scene : 0.571422
Fabric : 0.563129
Gray : 0.56078
Water Sport : 0.555034
Person : 0.533461
Mammal : 0.515725
Surface Water Sport : 0.511447
一度のリクエストに30ファイルを含めても普通に処理してくれました。
もしかしたらもっといけるかも。
書いたスクリプト
画像をcut
物体認識させて結果をjsonファイルに保存
結果のjsonファイルをcsvに出力
注意
今回ユーザ名やパスワードを設定ファイルから取得するためにpitというPythonのサードパーティパッケージを使用しています。ただし2015/04/12現在、pitはPython3には対応していないため、普通にPython3でpip install pitしてもエラーしてしまいます。
pitのリポジトリをフォークしてPython3対応したブランチがありますのでそこからpitをインストールして使用してください。
https://github.com/TakesxiSximada/pit/archive/fix/sximada/py3k.zip
https://github.com/TakesxiSximada/pit/tree/fix/sximada/py3k
...というかサボらずプルリク出せよ > 俺