Skip to content

Commit 803f0cd

Browse files
committed
Merge branch 'kognate-add_v3'
2 parents 34eaea0 + 3f14625 commit 803f0cd

File tree

6 files changed

+187
-2
lines changed

6 files changed

+187
-2
lines changed

examples/alchemy_language_v1.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# print(json.dumps(alchemy_language.concepts(max_items=2, url=url), indent=2))
1414
# print(json.dumps(alchemy_language.entities(url=url), indent=2))
1515
# print(json.dumps(alchemy_language.category(url=url), indent=2))
16+
# print(json.dumps(alchemy_language.typed_relations(url=url), indent=2))
1617
# print(json.dumps(alchemy_language.relations(url=url), indent=2))
1718
# print(json.dumps(alchemy_language.language(url=url), indent=2))
1819
# print(json.dumps(alchemy_language.text(url=url), indent=2))

examples/visual_recognition_v3.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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 = 'https://www.ibm.com/ibm/ginni/images/ginni_bio_780x981_v4_03162016.jpg'
7+
8+
visual_recognition = VisualRecognitionV3('2016-05-20', api_key='YOUR 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+
# print(json.dumps(visual_recognition.classify(images_file=image_file, threshold=0.1,
17+
# classifier_ids=['CarsvsTrucks_1675727418', 'default']), indent=2))
18+
19+
# print(json.dumps(visual_recognition.get_classifier('YOUR CLASSIFIER ID'), indent=2))
20+
21+
print(json.dumps(visual_recognition.classify(images_url=test_url), indent=2))
22+
23+
print(json.dumps(visual_recognition.detect_faces(images_url=test_url), indent=2))
24+
25+
# print(json.dumps(visual_recognition.delete_classifier(classifier_id='YOUR CLASSIFIER ID'), indent=2))
26+
27+
print(json.dumps(visual_recognition.list_classifiers(), indent=2))
28+
29+
with open(join(dirname(__file__), '../resources/text.png'), 'rb') as image_file:
30+
print(json.dumps(visual_recognition.recognize_text(images_file=image_file), indent=2))
31+
32+
with open(join(dirname(__file__), '../resources/face.jpg'), 'rb') as image_file:
33+
print(json.dumps(visual_recognition.detect_faces(images_file=image_file), 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__

watson_developer_cloud/alchemy_language_v1.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ def emotion(self, html=None, text=None, url=None, show_source_text=False, source
7171
'language': language}
7272
return self._alchemy_html_request('GetEmotion', html=html, text=text, url=url, params=params)
7373

74+
def typed_relations(self, html=None, text=None, url=None, model=None):
75+
params = {'model': model}
76+
return self._alchemy_html_request('GetTypedRelations', html=html, text=text, url=url, params=params)
77+
7478
def relations(self, html=None, text=None, url=None, sentiment=False, keywords=False, entities=False,
7579
require_entities=False, sentiment_excludes_entities=True, disambiguate=True, linked_data=True,
7680
coreference=True, show_source_text=False, max_items=50, language=None):
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
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+
import mimetypes
20+
21+
from .watson_developer_cloud_service import WatsonDeveloperCloudService
22+
23+
24+
class VisualRecognitionV3(WatsonDeveloperCloudService):
25+
"""Client for the Visual Recognition service"""
26+
27+
default_url = 'https://gateway-a.watsonplatform.net/visual-recognition/api'
28+
latest_version = '2016-05-20'
29+
30+
def __init__(self, version, url=default_url, use_vcap_services=True, api_key=None):
31+
"""
32+
Construct an instance. Fetches service parameters from VCAP_SERVICES
33+
runtime variable for Bluemix, or it defaults to local URLs.
34+
:param version: specifies the specific version-date of the service to use
35+
"""
36+
37+
WatsonDeveloperCloudService.__init__(
38+
self, 'watson_vision_combined', url, None, None, use_vcap_services, api_key)
39+
self.version = version
40+
41+
def get_classifier(self, classifier_id):
42+
"""
43+
Retrieves information about a specific classifier.
44+
:param classifier_id: The classifier id
45+
"""
46+
47+
params = {'version': self.version}
48+
return self.request(method='GET', url='/v3/classifiers/{0}'.format(classifier_id), params=params,
49+
accept_json=True)
50+
51+
def delete_classifier(self, classifier_id):
52+
"""
53+
Deletes a custom classifier with the specified classifier id.
54+
:param classifier_id: The classifier id
55+
"""
56+
57+
params = {'version': self.version}
58+
return self.request(method='DELETE', url='/v3/classifiers/{0}'.format(classifier_id), params=params,
59+
accept_json=True)
60+
61+
def list_classifiers(self, verbose=False):
62+
"""
63+
Returns a list of user-created and built-in classifiers. (May change in the future to only user-created.)
64+
:param verbose: Specifies whether to return more information about each classifier, such as the author
65+
"""
66+
67+
params = {'verbose': verbose, 'version': self.version}
68+
return self.request(method='GET', url='/v3/classifiers', params=params, accept_json=True)
69+
70+
def create_classifier(self, name, **kwargs):
71+
"""
72+
Train a new classifier from example images which are uploaded.
73+
:param name: The desired short name of the new classifier.
74+
:param <NAME>_positive_examples: Up to 5 zip files of images that depict the subject of the new classifier.
75+
:param negative_examples: A zip file of images that do not depict the subject of the new classifier.
76+
:return:
77+
"""
78+
79+
params = {'version': self.version}
80+
data = {'name': name}
81+
# Params sent as url parameters here
82+
return self.request(method='POST', url='/v3/classifiers', files=kwargs, data=data, params=params,
83+
accept_json=True)
84+
85+
def _image_call(self, url, images_file=None, images_url=None, params=None):
86+
if images_file is None and images_url is None:
87+
raise AssertionError('You must specify either a file or a url')
88+
89+
if images_url:
90+
params['url'] = images_url
91+
return self.request(method='GET', url=url, params=params, accept_json=True)
92+
else:
93+
filename = images_file.name
94+
mime_type = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
95+
return self.request(method='POST', url=url,
96+
files={'images_file': (filename, images_file, mime_type)}, params=params,
97+
accept_json=True)
98+
99+
def classify(self, images_file=None, images_url=None, classifier_ids=None, owners=None, threshold=None):
100+
"""
101+
Returns a list of classification scores for one or more input images.
102+
:param images_file: An image file or zip file of image files to analyze.
103+
:param images_url: The url for an image file or zip file of images to analyze.
104+
:param classifier_ids: The ids of classifiers to consider. When absent, considers all classifiers.
105+
:return:
106+
"""
107+
108+
if isinstance(classifier_ids, list):
109+
classifier_ids = ','.join(classifier_ids)
110+
if isinstance(owners, list):
111+
owners = ','.join(owners)
112+
113+
params = {'version': self.version, 'classifier_ids': classifier_ids, 'owners': owners, 'threshold': threshold}
114+
return self._image_call('/v3/classify', images_file, images_url, params)
115+
116+
def detect_faces(self, images_file=None, images_url=None):
117+
"""
118+
Returns a list of faces detected. This includes identities for famous people.
119+
:param images_file: An image file or zip file of image files to analyze.
120+
:param images_url: The url for an image file or zip file of images to analyze.
121+
:return:
122+
"""
123+
124+
params = {'version': self.version}
125+
return self._image_call('/v3/detect_faces', images_file, images_url, params)
126+
127+
def recognize_text(self, images_file=None, images_url=None):
128+
"""
129+
Returns a list of recognized text
130+
:param images_file: An image file or zip file of image files to analyze.
131+
:param images_url: The url for an image file or zip file of images to analyze.
132+
:return:
133+
"""
134+
135+
params = {'version': self.version}
136+
return self._image_call('/v3/recognize_text', images_file, images_url, params)

watson_developer_cloud/watson_developer_cloud_service.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,12 @@ def __init__(self, vcap_services_name, url, username=None, password=None, use_vc
9595
self.username = self.vcap_service_credentials['username']
9696
if 'password' in self.vcap_service_credentials:
9797
self.password = self.vcap_service_credentials['password']
98+
if 'api_key' in self.vcap_service_credentials:
99+
self.api_key = self.vcap_service_credentials['api_key']
98100
if 'apikey' in self.vcap_service_credentials:
99101
self.api_key = self.vcap_service_credentials['apikey']
102+
if 'api_key' in self.vcap_service_credentials:
103+
self.api_key = self.vcap_service_credentials['api_key']
100104

101105
if (self.username is None or self.password is None) and self.api_key is None:
102106
raise WatsonException('You must specific your username and password service credentials ' +
@@ -143,7 +147,10 @@ def _get_error_message(response):
143147
try:
144148
error_json = response.json()
145149
if 'error' in error_json:
146-
error_message = 'Error: ' + error_json['error']
150+
if isinstance(error_json['error'], dict) and 'description' in error_json['error']:
151+
error_message = 'Error: ' + error_json['error']['description']
152+
else:
153+
error_message = 'Error: ' + error_json['error']
147154
if 'error_message' in error_json:
148155
error_message = 'Error: ' + error_json['error_message']
149156
if 'description' in error_json:
@@ -227,7 +234,10 @@ def request(self, method, url, accept_json=False, headers=None, params=None, jso
227234
if self.api_key is not None:
228235
if params is None:
229236
params = {}
230-
params['apikey'] = self.api_key
237+
if url.startswith('https://gateway-a.watsonplatform.net/calls'):
238+
params['apikey'] = self.api_key
239+
else:
240+
params['api_key'] = self.api_key
231241

232242
response = requests.request(method=method, url=full_url, cookies=self.jar, auth=auth, headers=headers,
233243
params=params, data=data, files=files, **kwargs)

0 commit comments

Comments
 (0)