Skip to content

Commit 93ef6fc

Browse files
author
Joshua B. Smith
committed
First whack at v3 image recognition
This adds the v3 image recognition for python. This includes multi-class classifier, face detection, and text recognition.
1 parent 34eaea0 commit 93ef6fc

File tree

3 files changed

+171
-0
lines changed

3 files changed

+171
-0
lines changed

examples/visual_recognition_v3.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import json
2+
from os.path import join, dirname
3+
from os import environ
4+
from watson_developer_cloud import VisualRecognitionV3
5+
6+
test_url = 'http://ia.media-imdb.com/images/M/MV5BMTMxMDIzMDEzNF5BMl5BanBnXkFtZTcwODcxMjE2Mg@@._V1_UY317_CR2,0,214,317_AL_.jpg'
7+
8+
visual_recognition = VisualRecognitionV3('2016-05-20',api_key=environ['API_KEY'])
9+
10+
#with open(join(dirname(__file__), '../resources/cars.zip'), 'rb') as cars, \
11+
# open(join(dirname(__file__), '../resources/trucks.zip'), 'rb') as trucks:
12+
# print(json.dumps(visual_recognition.create_classifier('Cars vs Trucks', cars_positive_examples=cars,
13+
# negative_examples=trucks), indent=2))
14+
15+
#with open(join(dirname(__file__), '../resources/car.jpg'), 'rb') as image_file:
16+
# visual_recognition.classify(images_file=image_file)
17+
18+
print(json.dumps(visual_recognition.classify(images_url=test_url), indent=2))
19+
20+
21+
#The service currently has a bug where even successful deletions return a 404
22+
#print(json.dumps(visual_recognition.delete_classifier(classifier_id='YOUR CLASSIFIER ID'), indent=2))
23+
24+
#print(json.dumps(visual_recognition.list_classifiers(), indent=2))
25+
26+
# with open(join(dirname(__file__), '../resources/test.jpg'), 'rb') as image_file:
27+
# print(json.dumps(visual_recognition.classify(image_file, classifier_ids=['Tiger', 'Cat']), indent=2))

watson_developer_cloud/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,5 @@
3737
from .visual_insights_v1_experimental import VisualInsightsV1Experimental
3838
from .visual_recognition_v1_beta import VisualRecognitionV1Beta
3939
from .visual_recognition_v2_beta import VisualRecognitionV2Beta
40+
from .visual_recognition_v3 import VisualRecognitionV3
4041
from .version import __version__
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Copyright 2015 IBM All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
"""
15+
The v3 Visual Recognition service
16+
(http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/visual-recognition/)
17+
"""
18+
import json
19+
from .watson_developer_cloud_service import WatsonDeveloperCloudService
20+
21+
22+
class VisualRecognitionV3(WatsonDeveloperCloudService):
23+
24+
"""Client for the Visual Recognition service"""
25+
26+
default_url = 'https://gateway-a.watsonplatform.net/visual-recognition/api'
27+
latest_version = '2016-05-20'
28+
29+
def __init__(self, version, url=default_url, use_vcap_services=True, api_key=None):
30+
"""
31+
Construct an instance. Fetches service parameters from VCAP_SERVICES
32+
runtime variable for Bluemix, or it defaults to local URLs.
33+
:param version: specifies the specific version-date of the service to use
34+
"""
35+
36+
WatsonDeveloperCloudService.__init__(
37+
self, 'visual_recognition', url, None, None, use_vcap_services, api_key)
38+
self.version = version
39+
40+
def get_classifier(self, classifier_id):
41+
"""
42+
Retrieves information about a specific classifier.
43+
:param classifier_id: The classifier id
44+
"""
45+
46+
params = {'version': self.version}
47+
return self.request(method='GET', url='/v3/classifiers/{0}'.format(classifier_id), params=params,
48+
accept_json=True)
49+
50+
def delete_classifier(self, classifier_id):
51+
"""
52+
Deletes a custom classifier with the specified classifier id.
53+
:param classifier_id: The classifier id
54+
"""
55+
56+
params = {'version': self.version}
57+
return self.request(method='DELETE', url='/v3/classifiers/{0}'.format(classifier_id), params=params,
58+
accept_json=True)
59+
60+
def list_classifiers(self, verbose=False):
61+
"""
62+
Returns a list of user-created and built-in classifiers. (May change in the future to only user-created.)
63+
:param verbose: Specifies whether to return more information about each classifier, such as the author
64+
"""
65+
66+
params = {'verbose': verbose, 'version': self.version}
67+
return self.request(method='GET', url='/v3/classifiers', params=params, accept_json=True)
68+
69+
def create_classifier(self, name, **kwargs):
70+
"""
71+
Train a new classifier from example images which are uploaded.
72+
:param name: The desired short name of the new classifier.
73+
:param <NAME>_positive_examples: Up to 5 zip files of images that depict the subject of the new classifier.
74+
:param negative_examples: A zip file of images that do not depict the subject of the new classifier.
75+
:return:
76+
"""
77+
78+
params = {'version': self.version}
79+
data = {'name': name}
80+
# Params sent as url parameters here
81+
return self.request(method='POST', url='/v3/classifiers', files=kwargs,
82+
data=data, params=params, accept_json=True)
83+
84+
def classify(self, images_file=None, images_url=None, classifier_ids=None):
85+
"""
86+
Returns a list of classification scores for one or more input images.
87+
:param images_file: An image file or zip file of image files to analyze.
88+
:param classifier_ids: The ids of classifiers to consider. When absent, considers all classifiers.
89+
:return:
90+
"""
91+
92+
if isinstance(classifier_ids, list):
93+
classifier_ids = json.dumps(classifier_ids)
94+
if classifier_ids:
95+
classifier_ids = '{"classifier_ids": ' + classifier_ids + '}'
96+
97+
if images_file == None and images_url == None:
98+
raise AssertionError('You must specify either a file or a url')
99+
100+
params = {'version': self.version}
101+
data = {'classifier_ids': classifier_ids}
102+
# Params sent as url parameters here
103+
if images_url:
104+
params['url'] = images_url
105+
return self.request(method='POST', url='/v3/classify', data=data, params=params, accept_json=True)
106+
else:
107+
return self.request(method='POST', url='/v3/classify', files={'images_file': images_file }, data=data, params=params, accept_json=True)
108+
109+
110+
def detect_faces(self, images_file=None, images_url=None):
111+
"""
112+
Returns a list of faces detected. This includes identities for famous people.
113+
:param images_file: An image file or zip file of image files to analyze.
114+
:return:
115+
"""
116+
117+
params = {'version': self.version}
118+
# Params sent as url parameters here
119+
if images_url:
120+
params['url'] = images_url
121+
return self.request(method='POST', url='/v3/detect_faces', params=params, accept_json=True)
122+
else:
123+
return self.request(method='POST', url='/v3/detect_faces', files={'images_file': images_file},
124+
params=params, accept_json=True)
125+
126+
def recognize_text(self, images_file=None, images_url=None):
127+
"""
128+
Returns a list of recognized text
129+
:param images_file: An image file or zip file of image files to analyze.
130+
:return:
131+
"""
132+
133+
params = {'version': self.version}
134+
# Params sent as url parameters here
135+
if images_url:
136+
params['url'] = images_url
137+
return self.request(method='POST', url='/v3/recognize_text', params=params, accept_json=True)
138+
else:
139+
return self.request(method='POST', url='/v3/recognize_text',
140+
files={'images_file': images_file}, params=params, accept_json=True)
141+
142+
143+

0 commit comments

Comments
 (0)