Skip to content

Commit 976e8ed

Browse files
committed
Add Vision Client.
1 parent a1ae30b commit 976e8ed

File tree

11 files changed

+1877
-1
lines changed

11 files changed

+1877
-1
lines changed

docs/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@
148148

149149
vision-usage
150150
vision-client
151+
vision-image
152+
vision-feature
151153

152154
.. toctree::
153155
:maxdepth: 0

docs/vision-client.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
Vision Client
2-
================
2+
=============
3+
4+
Client
5+
~~~~~~
6+
7+
.. automodule:: gcloud.vision.client
8+
:members:
9+
:undoc-members:
10+
:show-inheritance:
311

412
Connection
513
~~~~~~~~~~

docs/vision-feature.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Vision Feature
2+
==============
3+
4+
Feature
5+
~~~~~~~
6+
7+
.. automodule:: gcloud.vision.feature
8+
:members:
9+
:undoc-members:
10+
:show-inheritance:

docs/vision-image.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Vision Image
2+
============
3+
4+
Image
5+
~~~~~
6+
7+
.. automodule:: gcloud.vision.image
8+
:members:
9+
:undoc-members:
10+
:show-inheritance:

gcloud/vision/client.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Copyright 2016 Google Inc. 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+
"""Client for interacting with the Google Cloud Vision API."""
16+
17+
import json
18+
from json import JSONEncoder
19+
20+
from gcloud.client import JSONClient
21+
from gcloud.vision.connection import Connection
22+
from gcloud.vision.feature import Feature
23+
from gcloud.vision.image import Image
24+
25+
26+
class VisionJSONEncoder(JSONEncoder):
27+
def default(self, o):
28+
if 'as_dict' in dir(o):
29+
return o.as_dict()
30+
else:
31+
return o.__dict__
32+
33+
34+
class VisionRequest(object):
35+
def __init__(self, image, feature):
36+
self._features = []
37+
self._image = image
38+
39+
if isinstance(feature, list):
40+
self._features.extend(feature)
41+
elif isinstance(feature, Feature):
42+
self._features.append(feature)
43+
else:
44+
raise TypeError('Feature or list of Feature classes are required.')
45+
46+
def as_dict(self):
47+
return {
48+
'image': self.image,
49+
'features': self.features
50+
}
51+
52+
@property
53+
def features(self):
54+
return self._features
55+
56+
@property
57+
def image(self):
58+
return self._image
59+
60+
61+
class Client(JSONClient):
62+
"""Client to bundle configuration needed for API requests.
63+
64+
:type project: str
65+
:param project: the project which the client acts on behalf of.
66+
If not passed, falls back to the default inferred
67+
from the environment.
68+
69+
:type credentials: :class:`oauth2client.client.OAuth2Credentials` or
70+
:class:`NoneType`
71+
:param credentials: The OAuth2 Credentials to use for the connection
72+
owned by this client. If not passed (and if no ``http``
73+
object is passed), falls back to the default inferred
74+
from the environment.
75+
76+
:type http: :class:`httplib2.Http` or class that defines ``request()``.
77+
:param http: An optional HTTP object to make requests. If not passed, an
78+
``http`` object is created that is bound to the
79+
``credentials`` for the current object.
80+
"""
81+
82+
_connection_class = Connection
83+
84+
def annotate(self, image, features=[]):
85+
"""Annotate an image to discover it's attributes.
86+
87+
:type image: str
88+
:param image: A string which can be a URL, a Google Cloud Storage path,
89+
or a byte stream of the image.
90+
91+
:type features: list
92+
:param features: The type of detection that the Vision API should
93+
use to determine image attributes. Pricing is
94+
based on the number of Feature Types.
95+
96+
See: https://cloud.google.com/vision/docs/pricing
97+
"""
98+
data = {'requests': []}
99+
100+
img = Image(image, self)
101+
data['requests'].append(VisionRequest(img, features))
102+
103+
data = json.dumps(data, cls=VisionJSONEncoder)
104+
response = self.connection.api_request(method='POST',
105+
path='/images:annotate',
106+
data=data)
107+
return response['responses'][0]

gcloud/vision/feature.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Copyright 2016 Google Inc. 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+
16+
class FeatureTypes(object):
17+
"""Feature Types to indication which annotations to perform.
18+
19+
See:
20+
https://cloud.google.com/vision/reference/rest/v1/images/annotate#Type
21+
"""
22+
FACE_DETECTION = 'FACE_DETECTION'
23+
LANDMARK_DETECTION = 'LANDMARK_DETECTION'
24+
LOGO_DETECTION = 'LOGO_DETECTION'
25+
LABEL_DETECTION = 'LABEL_DETECTION'
26+
TEXT_DETECTION = 'TEXT_DETECTION'
27+
SAFE_SEARCH_DETECTION = 'SAFE_SEARCH_DETECTION'
28+
29+
30+
class Feature(object):
31+
"""Feature object specifying the annotation type and maximum results.
32+
33+
:type feature_type: str
34+
:param feature_type: String representation of feature type.
35+
36+
:type max_results: int
37+
:param max_results: Number of results to return for the specified
38+
feature type.
39+
40+
See:
41+
https://cloud.google.com/vision/reference/rest/v1/images/annotate#Feature
42+
"""
43+
def __init__(self, feature_type, max_results=1):
44+
self._feature_type = getattr(FeatureTypes, feature_type)
45+
self._max_results = int(max_results)
46+
47+
def as_dict(self):
48+
"""Generate dictionary for Feature request format."""
49+
return {
50+
'type': self.feature_type,
51+
'maxResults': self.max_results
52+
}
53+
54+
@property
55+
def feature_type(self):
56+
""""Feature type string."""
57+
return self._feature_type
58+
59+
@property
60+
def max_results(self):
61+
"""Maximum number of results for feature type."""
62+
return self._max_results

0 commit comments

Comments
 (0)