Skip to content

Commit

Permalink
Initial vision API addition.
Browse files Browse the repository at this point in the history
  • Loading branch information
daspecster committed May 17, 2016
1 parent f8ddb2a commit 99365d6
Show file tree
Hide file tree
Showing 10 changed files with 673 additions and 0 deletions.
18 changes: 18 additions & 0 deletions gcloud/vision/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Google Cloud Vision API package."""


from gcloud.vision.client import Client
100 changes: 100 additions & 0 deletions gcloud/vision/annotation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Define annotations."""


class EntityAnnotation(object):
_mid = None
_locale = None
_description = None
_score = None
_confidence = None
_topicality = None
_bounding_poly = None
_locations = []
_properties = []

def __init__(self, mid, locale, description, score, confidence, topicality,
bounding_poly, locations, properties):
self._mid = mid
self._locale = locale
self._description = description
self._score = score
self._confidence = confidence
self._topicality = topicality
self._bounding_poly = bounding_poly
self._locations = locations
self._properties = properties

@property
def mid(self):
return self._mid

@property
def locale(self):
return self._locale

@property
def description(self):
return self._description

@property
def score(self):
return self._score

@property
def confidence(self):
return self._confidence

@property
def topicality(self):
return self._topicality

@property
def bounding_poly(self):
return self._bounding_poly

@property
def locations(self):
return self._locations

@property
def properties(self):
return self._properties


class LabelAnnotation(EntityAnnotation):
def __init__(self):
raise NotImplementedError


class LandmarkAnnotation(EntityAnnotation):
def __init__(self):
raise NotImplementedError


class LogoAnnotation(EntityAnnotation):
def __init__(self):
raise NotImplementedError


class TextAnnotation(EntityAnnotation):
def __init__(self):
raise NotImplementedError


class SafeSearchAnnotation(EntityAnnotation):
def __init__(self):
raise NotImplementedError
136 changes: 136 additions & 0 deletions gcloud/vision/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Client for interacting with the Google Cloud Vision API."""

import json
from json import JSONEncoder

from gcloud.client import JSONClient
from gcloud.vision.connection import Connection
from gcloud.vision.feature import Feature
from gcloud.vision.image import Image


class VisionJSONEncoder(JSONEncoder):
def default(self, o):
if 'as_dict' in dir(o):
return o.as_dict()
else:
return o.__dict__


class VisionRequest(object):
def __init__(self, image, feature):
self._features = []
self._image = image

if type(feature) == list:
self._features.extend(feature)
elif type(feature) == Feature:
self._features.append(feature)

def as_dict(self):
return {
"image": self.image,
"features": self.features
}

@property
def features(self):
return self._features

@property
def image(self):
return self._image


class Client(JSONClient):
"""Client to bundle configuration needed for API requests.
:type project: str
:param project: the project which the client acts on behalf of.
If not passed, falls back to the default inferred
from the environment.
:type credentials: :class:`oauth2client.client.OAuth2Credentials` or
:class:`NoneType`
:param credentials: The OAuth2 Credentials to use for the connection
owned by this client. If not passed (and if no ``http``
object is passed), falls back to the default inferred
from the environment.
:type http: :class:`httplib2.Http` or class that defines ``request()``.
:param http: An optional HTTP object to make requests. If not passed, an
``http`` object is created that is bound to the
``credentials`` for the current object.
Usage:
>>> from gcloud import vision
>>> vision_client = vision.Client()
>>> f = open('/tmp/car.jpg', 'r')
>>> vision_client.annotate(f.read(), "LABEL_DETECTION", 3)
Multiple images example:
>>> images = (("./image.jpg", ["LABEL_DETECTION", "LANDMARK_DETECTION"]),
>>> ("./image2.jpg", ["FACE_DETECTION", "TEXT_DETECTION"]),)
>>> annotated_images = []
>>> for image, feature_types in images:
>>> annotated_images.append(vision_client.annotate(image,
>>> feature_types))
"""

_connection_class = Connection

def annotate(self, image, feature_type, max_results=1):
"""Annotate an image to discover it's attributes.
:type image: str
:param image: A string which can be a URL, a Google Cloud Storage path,
or a byte stream of the image.
:type feature_type: str or list
:param feature_type: The type of detection that the Vision API should
use to determine image attributes. *Pricing is
based on the number of Feature Types.
See:
https://cloud.google.com/vision/docs/pricing
:type max_results: int
:param max_results: The number of results per feature type to be
returned.
"""
vision_requests = []
features = []

if type(image) == str:
img = Image(image)

if type(feature_type) == list:
for feature in feature_type:
features.append(Feature(feature, max_results))
else:
features.append(Feature(feature_type, max_results))

vision_requests.append(VisionRequest(img, features))

data = {"requests": vision_requests}
data = json.dumps(data, cls=VisionJSONEncoder)
resp = self.connection.api_request(method="POST",
path="/images:annotate",
data=data)
resp = resp['responses']
return resp
47 changes: 47 additions & 0 deletions gcloud/vision/connection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""Create / interact with gcloud Vision connections."""


from gcloud import connection as base_connection


class Connection(base_connection.JSONConnection):
"""A connection to Google Cloud Vision via the JSON REST API.
:type credentials: :class:`oauth2client.client.OAuth2Credentials`
:param credentials: (Optional) The OAuth2 Credentials to use for this
connection.
:type http: :class:`httplib2.Http` or class that defines ``request()``.
:param http: (Optional) HTTP object to make requests.
:type api_base_url: string
:param api_base_url: The base of the API call URL. Defaults to the value
:attr:`Connection.API_BASE_URL`.
"""

API_BASE_URL = 'https://vision.googleapis.com'
"""The base of the API call URL."""

API_VERSION = 'v1'
"""The version of the API, used in building the API call's URL."""

API_URL_TEMPLATE = '{api_base_url}/{api_version}{path}'
"""A template for the URL of a particular API call."""

SCOPE = ('https://www.googleapis.com/auth/cloud-platform',)
"""The scopes required for authenticating as a Cloud Vision consumer."""
63 changes: 63 additions & 0 deletions gcloud/vision/feature.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


class FeatureTypes(object):
"""Feature Types to indication which annotations to perform.
See:
https://cloud.google.com/vision/reference/rest/v1/images/annotate#Type
"""
FACE_DETECTION = "FACE_DETECTION"
LANDMARK_DETECTION = "LANDMARK_DETECTION"
LOGO_DETECTION = "LOGO_DETECTION"
LABEL_DETECTION = "LABEL_DETECTION"
TEXT_DETECTION = "TEXT_DETECTION"
SAFE_SEARCH_DETECTION = "SAFE_SEARCH_DETECTION"


class Feature(object):
"""Feature object specifying the annotation and number of results for the
specified feature type.
:type feature_type: str
:param feature_type: String representation of feature type.
:type max_results: int
:param max_results: Number of results to return for the specified
feature type.
See:
https://cloud.google.com/vision/reference/rest/v1/images/annotate#Feature
"""
def __init__(self, feature_type, max_results=1):
self._feature_type = getattr(FeatureTypes, feature_type)
self._max_results = int(max_results)

def as_dict(self):
"""Generate dictionary for Feature request format."""
return {
"type": self.feature_type,
"maxResults": self.max_results
}

@property
def feature_type(self):
""""Feature type string."""
return self._feature_type

@property
def max_results(self):
"""Maximum number of results for feature type."""
return self._max_results
Loading

0 comments on commit 99365d6

Please sign in to comment.