From f1968cf34241dee0aea32e8628ae2a3f71588032 Mon Sep 17 00:00:00 2001 From: Newmu Date: Thu, 11 Sep 2014 20:17:25 -0400 Subject: [PATCH 1/5] Updated to included image features api and sphinx compliant documentation --- CHANGES.txt | 1 + README | 7 ++++++- README.md | 7 ++++++- indicoio/__init__.py | 3 ++- indicoio/images/features.py | 37 +++++++++++++++++++++++++++++++++++++ indicoio/utils/__init__.py | 19 +++++++++++++++++++ setup.py | 2 +- 7 files changed, 72 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 65fe504..58f2cbc 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,3 +8,4 @@ v0.3.3, Fri Aug 1 -- Added language detection api v0.4.0, Fri Aug 1 -- Changed api import to lowercase, added language example v0.4.1, Fri Aug 1 -- Updated __version__ variable to be accurate v0.4.2, Wed Aug 6 -- Updated README to accurately reflect political analysis results +v0.4.3, Thu Sep 11 -- Added image features api and sphinx compliant documentation diff --git a/README b/README index 1efd8d6..45cf0d9 100644 --- a/README +++ b/README @@ -7,6 +7,10 @@ Check out the main site on: http://indico.io +Check out our documentation on: + +http://indicoiopython.s3-website-us-west-2.amazonaws.com/indicoio.html + Our APIs are totally free to use, and ready to be used in your application. No data or training required. Current APIs @@ -14,8 +18,9 @@ Current APIs Right now this wrapper supports the following apps: -- Political Sentiment Analysis - Positive/Negative Sentiment Analysis +- Political Sentiment Analysis +- Image Feature Extraction - Facial Emotion Recognition - Facial Feature Extraction - Language Detection diff --git a/README.md b/README.md index 1efd8d6..45cf0d9 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,10 @@ Check out the main site on: http://indico.io +Check out our documentation on: + +http://indicoiopython.s3-website-us-west-2.amazonaws.com/indicoio.html + Our APIs are totally free to use, and ready to be used in your application. No data or training required. Current APIs @@ -14,8 +18,9 @@ Current APIs Right now this wrapper supports the following apps: -- Political Sentiment Analysis - Positive/Negative Sentiment Analysis +- Political Sentiment Analysis +- Image Feature Extraction - Facial Emotion Recognition - Facial Feature Extraction - Language Detection diff --git a/indicoio/__init__.py b/indicoio/__init__.py index 76d4a39..d3d3739 100644 --- a/indicoio/__init__.py +++ b/indicoio/__init__.py @@ -1,9 +1,10 @@ JSON_HEADERS = {'Content-type': 'application/json', 'Accept': 'text/plain'} -Version, version, __version__, VERSION = ('0.4.2',) * 4 +Version, version, __version__, VERSION = ('0.4.3',) * 4 from text.sentiment import political, posneg from text.sentiment import posneg as sentiment from text.lang import language from images.fer import fer from images.features import facial_features +from images.features import image_features \ No newline at end of file diff --git a/indicoio/images/features.py b/indicoio/images/features.py index cac6475..83c95af 100644 --- a/indicoio/images/features.py +++ b/indicoio/images/features.py @@ -4,6 +4,7 @@ import requests import numpy as np from indicoio import JSON_HEADERS +from indicoio.utils import image_preprocess def facial_features(image): """ @@ -32,3 +33,39 @@ def facial_features(image): response = requests.post("http://api.indico.io/facialfeatures", data=data_dict, headers=JSON_HEADERS) response_dict = json.loads(response.content) return response_dict['response'] + +def image_features(image): + """ + Given an input image, returns a 2048 dimensional sparse feature vector explaining that image. + Useful as a form of feature engineering for image oriented tasks. + + * Input can be either grayscale or rgb color and should either be a numpy array or nested list format. + * Input data should be either uint8 0-255 range values or floating point between 0 and 1. + * Large images (i.e. 1024x768+) are much bigger than needed, resizing will be done internally to 64x64 if needed. + * For ideal performance, images should be square aspect ratio but non-square aspect ratios are supported as well. + + Example usage: + + .. code-block:: python + + >>> from indicoio import image_features + >>> import numpy as np + >>> image = np.zeros((64,64,3)) + >>> features = image_features(image) + >>> len(features),np.min(features),np.max(features),np.sum(np.asarray(f)!=0) + (2048, 0.0, 6.97088623046875, 571) + + Since the image features returned are a semantic description of the contents of an image they can be used + to implement many other common image related tasks such as object recognition or image similarity and retrieval. + + For image similarity, simple distance metrics applied to collections of image feature vectors can work very well. + + :param image: The image to be analyzed. + :type image: numpy.ndarray + :rtype: List containing features + """ + image = image_preprocess(image) + data_dict = json.dumps({"image": image}) + response = requests.post("http://api.indico.io/imagefeatures", data=data_dict, headers=JSON_HEADERS) + response_dict = json.loads(response.content) + return response_dict['Features'] \ No newline at end of file diff --git a/indicoio/utils/__init__.py b/indicoio/utils/__init__.py index 7272f87..cd39b3d 100644 --- a/indicoio/utils/__init__.py +++ b/indicoio/utils/__init__.py @@ -1,5 +1,6 @@ import inspect import numpy as np +from skimage.transform import resize class TypeCheck(object): """ @@ -84,3 +85,21 @@ def normalize(array, distribution=1, norm_range=(0, 1), **kwargs): if dict_array: return dict(zip(keys, norm_array)) return norm_array + +def image_preprocess(image): + """ + Takes an image and prepares it for sending to the api including + resizing and image data/structure standardizing. + """ + if isinstance(image,list): + image = np.asarray(image) + if image.max() > 1: + image = image/255. + if len(image.shape) == 2: + image = np.dstack((image,image,image)) + if len(image.shape) == 4: + image = image[:,:,:3] + + image = resize(image,(64,64)) + image = image.tolist() + return image \ No newline at end of file diff --git a/setup.py b/setup.py index 34ad457..dfe9649 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ except ImportError: setup( name="IndicoIo", - version='0.4.2', + version='0.4.3', packages=[ "indicoio", "indicoio.text", From d6cb1bf1d90b5617e87c3edda62ab5f2a7ff848d Mon Sep 17 00:00:00 2001 From: Newmu Date: Fri, 12 Sep 2014 13:12:25 -0400 Subject: [PATCH 2/5] Added api error handeling and updated docs --- indicoio/images/features.py | 14 ++++++++++---- indicoio/images/fer.py | 6 +++++- indicoio/text/lang.py | 6 +++++- indicoio/text/sentiment.py | 18 +++++++++++++----- indicoio/utils/__init__.py | 2 ++ 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/indicoio/images/features.py b/indicoio/images/features.py index 83c95af..d6b049b 100644 --- a/indicoio/images/features.py +++ b/indicoio/images/features.py @@ -31,8 +31,11 @@ def facial_features(image): data_dict = json.dumps({"face": image}) response = requests.post("http://api.indico.io/facialfeatures", data=data_dict, headers=JSON_HEADERS) - response_dict = json.loads(response.content) - return response_dict['response'] + response_dict = response.json() + if 'response' not in response_dict: + raise ValueError(response_dict.values()[0]) + else: + return response_dict['response'] def image_features(image): """ @@ -67,5 +70,8 @@ def image_features(image): image = image_preprocess(image) data_dict = json.dumps({"image": image}) response = requests.post("http://api.indico.io/imagefeatures", data=data_dict, headers=JSON_HEADERS) - response_dict = json.loads(response.content) - return response_dict['Features'] \ No newline at end of file + response_dict = response.json() + if 'Features' not in response_dict: + raise ValueError(response_dict.values()[0]) + else: + return response_dict['Features'] \ No newline at end of file diff --git a/indicoio/images/fer.py b/indicoio/images/fer.py index d9fcf94..f66e063 100644 --- a/indicoio/images/fer.py +++ b/indicoio/images/fer.py @@ -30,4 +30,8 @@ def fer(image): data_dict = json.dumps({"face": image}) response = requests.post("http://api.indico.io/fer", data=data_dict, headers=JSON_HEADERS) - return json.loads(response.content) + response_dict = response.json() + if len(response_dict) < 2: + raise ValueError(response_dict.values()[0]) + else: + return response_dict diff --git a/indicoio/text/lang.py b/indicoio/text/lang.py index fd56ac6..d4b6767 100644 --- a/indicoio/text/lang.py +++ b/indicoio/text/lang.py @@ -28,4 +28,8 @@ def language(text): data_dict = json.dumps({'text': text}) response = requests.post("http://api.indico.io/language", data=data_dict, headers=JSON_HEADERS) - return json.loads(response.content) \ No newline at end of file + response_dict = response.json() + if len(response_dict) < 2: + raise ValueError(response_dict.values()[0]) + else: + return response_dict \ No newline at end of file diff --git a/indicoio/text/sentiment.py b/indicoio/text/sentiment.py index 8e7f004..ba5e8fe 100644 --- a/indicoio/text/sentiment.py +++ b/indicoio/text/sentiment.py @@ -32,13 +32,17 @@ def political(text): data_dict = json.dumps({'text': text}) response = requests.post("http://api.indico.io/political", data=data_dict, headers=JSON_HEADERS) - return json.loads(response.content) + response_dict = response.json() + if len(response_dict) < 2: + raise ValueError(response_dict.values()[0]) + else: + return response_dict def posneg(text): """ Given input text, returns a scalar estimate of the sentiment of that text. Values are roughly in the range 0 to 1 with 0.5 indicating neutral sentiment. - Likewise, 0 would suggest very negative sentiment and 1 would suggest very positive sentiment. + For reference, 0 suggests very negative sentiment and 1 suggests very positive sentiment. Example usage: @@ -48,13 +52,17 @@ def posneg(text): >>> text = 'Thanks everyone for the birthday wishes!! It was a crazy few days ><' >>> sentiment = sentiment(text) >>> sentiment - {u'Sentiment': 0.6946439339979863} + 0.6946439339979863 :param text: The text to be analyzed. :type text: str or unicode - :rtype: Dictionary containing Sentiment key with a float value + :rtype: Float """ data_dict = json.dumps({'text': text}) response = requests.post("http://api.indico.io/sentiment", data=data_dict, headers=JSON_HEADERS) - return json.loads(response.content) + response_dict = response.json() + if 'Sentiment' not in response_dict: + raise ValueError(response_dict.values()[0]) + else: + return response_dict['Sentiment'] diff --git a/indicoio/utils/__init__.py b/indicoio/utils/__init__.py index cd39b3d..12c83ab 100644 --- a/indicoio/utils/__init__.py +++ b/indicoio/utils/__init__.py @@ -93,6 +93,8 @@ def image_preprocess(image): """ if isinstance(image,list): image = np.asarray(image) + if type(image).__module__ != np.__name__: + raise ValueError('Image was not of type numpy.ndarray or list.') if image.max() > 1: image = image/255. if len(image.shape) == 2: From e6fac9ad6a30a997f05f17ce3bc279ecd35da2bd Mon Sep 17 00:00:00 2001 From: Newmu Date: Fri, 12 Sep 2014 14:48:06 -0400 Subject: [PATCH 3/5] Fixed uint8 all zeros bug --- indicoio/utils/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/indicoio/utils/__init__.py b/indicoio/utils/__init__.py index 12c83ab..4da1e26 100644 --- a/indicoio/utils/__init__.py +++ b/indicoio/utils/__init__.py @@ -95,13 +95,14 @@ def image_preprocess(image): image = np.asarray(image) if type(image).__module__ != np.__name__: raise ValueError('Image was not of type numpy.ndarray or list.') - if image.max() > 1: + if str(image.dtype) in ['int64','uint8']: image = image/255. if len(image.shape) == 2: image = np.dstack((image,image,image)) if len(image.shape) == 4: image = image[:,:,:3] - + print image + print image.dtype,image.min(),image.max() image = resize(image,(64,64)) image = image.tolist() return image \ No newline at end of file From 19c32dbf66cad080b082aa7ba741f1da9ce06ea1 Mon Sep 17 00:00:00 2001 From: Newmu Date: Fri, 12 Sep 2014 14:49:36 -0400 Subject: [PATCH 4/5] updated readme --- README | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README b/README index 45cf0d9..de1bd75 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ indicoio-python =============== -A wrapper for a series of APIs made by Indico Data Solutions. +A wrapper for a series of APIs made by indico. Check out the main site on: diff --git a/README.md b/README.md index 45cf0d9..de1bd75 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ indicoio-python =============== -A wrapper for a series of APIs made by Indico Data Solutions. +A wrapper for a series of APIs made by indico. Check out the main site on: From 0c365cb79394036d54ca5af05ce3dcdd740a53dd Mon Sep 17 00:00:00 2001 From: Newmu Date: Fri, 12 Sep 2014 15:32:02 -0400 Subject: [PATCH 5/5] removing debug code --- indicoio/utils/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/indicoio/utils/__init__.py b/indicoio/utils/__init__.py index 4da1e26..18ae6db 100644 --- a/indicoio/utils/__init__.py +++ b/indicoio/utils/__init__.py @@ -101,8 +101,6 @@ def image_preprocess(image): image = np.dstack((image,image,image)) if len(image.shape) == 4: image = image[:,:,:3] - print image - print image.dtype,image.min(),image.max() image = resize(image,(64,64)) image = image.tolist() return image \ No newline at end of file