mirror of
https://github.com/wassname/IndicoIo-python.git
synced 2026-08-11 11:12:45 +08:00
Merge pull request #70 from IndicoDataSolutions/development
Development
This commit is contained in:
@@ -26,3 +26,4 @@ v0.6.0, Thu May 29 -- Remove numpy / scipy dependency in favor of Pillow
|
|||||||
v0.7.0, Tue Jun 9 -- Added support for calling multiple APIs in a single function and accepting filenames as image API inputs
|
v0.7.0, Tue Jun 9 -- Added support for calling multiple APIs in a single function and accepting filenames as image API inputs
|
||||||
v0.7.1 Thu Jun 11 -- High quality sentiment API for private beta, fix for multi API support
|
v0.7.1 Thu Jun 11 -- High quality sentiment API for private beta, fix for multi API support
|
||||||
v0.7.2 Thu Jun 11 -- Remove sentiment_hq from text apis by default
|
v0.7.2 Thu Jun 11 -- Remove sentiment_hq from text apis by default
|
||||||
|
v0.7.3 Wed Jun 17 -- Fixes for handling of specific image types
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
Version, version, __version__, VERSION = ('0.7.2',) * 4
|
Version, version, __version__, VERSION = ('0.7.3',) * 4
|
||||||
|
|
||||||
JSON_HEADERS = {
|
JSON_HEADERS = {
|
||||||
'Content-type': 'application/json',
|
'Content-type': 'application/json',
|
||||||
|
|||||||
+16
-10
@@ -22,7 +22,7 @@ def image_preprocess(image, size=(48,48), batch=False):
|
|||||||
b64_str = re.sub('^data:image/.+;base64,', '', image)
|
b64_str = re.sub('^data:image/.+;base64,', '', image)
|
||||||
if os.path.isfile(image):
|
if os.path.isfile(image):
|
||||||
# check type of element
|
# check type of element
|
||||||
outImage = Image.open(image)
|
out_image = Image.open(image)
|
||||||
elif B64_PATTERN.match(b64_str) is not None:
|
elif B64_PATTERN.match(b64_str) is not None:
|
||||||
return b64_str
|
return b64_str
|
||||||
else:
|
else:
|
||||||
@@ -33,20 +33,26 @@ def image_preprocess(image, size=(48,48), batch=False):
|
|||||||
"Input as lists of pixels will be deprecated in the next major update",
|
"Input as lists of pixels will be deprecated in the next major update",
|
||||||
DeprecationWarning
|
DeprecationWarning
|
||||||
)
|
)
|
||||||
outImage = process_list_image(image)
|
out_image = process_list_image(image)
|
||||||
elif isinstance(image, Image.Image):
|
elif isinstance(image, Image.Image):
|
||||||
outImage = image
|
out_image = image
|
||||||
elif type(image).__name__ == "ndarray": # image is from numpy/scipy
|
elif type(image).__name__ == "ndarray": # image is from numpy/scipy
|
||||||
out_image = Image.fromarray(image)
|
if "float" in str(image.dtype) and image.min() >= 0 and image.max() <= 1:
|
||||||
|
image *= 255.
|
||||||
|
try:
|
||||||
|
out_image = Image.fromarray(image.astype("uint8"))
|
||||||
|
except TypeError as e:
|
||||||
|
raise IndicoError("Please ensure the numpy array is acceptable by PIL. Values must be between 0 and 1 or between 0 and 255 in greyscale, rgb, or rgba format.")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise IndicoError("Image must be a filepath, base64 encoded string, or a numpy array")
|
raise IndicoError("Image must be a filepath, base64 encoded string, or a numpy array")
|
||||||
|
|
||||||
# image resizing
|
# image resizing
|
||||||
outImage = outImage.resize(size)
|
out_image = out_image.resize(size)
|
||||||
|
|
||||||
# convert to base64
|
# convert to base64
|
||||||
temp_output = StringIO.StringIO()
|
temp_output = StringIO.StringIO()
|
||||||
outImage.save(temp_output, format='PNG')
|
out_image.save(temp_output, format='PNG')
|
||||||
temp_output.seek(0)
|
temp_output.seek(0)
|
||||||
output_s = temp_output.read()
|
output_s = temp_output.read()
|
||||||
|
|
||||||
@@ -87,7 +93,7 @@ def process_list_image(_list):
|
|||||||
|
|
||||||
seq_obj = []
|
seq_obj = []
|
||||||
|
|
||||||
outImage = Image.new("RGB", (dimens[0], dimens[1]))
|
out_image = Image.new("RGB", (dimens[0], dimens[1]))
|
||||||
for i in xrange(dimens[0]):
|
for i in xrange(dimens[0]):
|
||||||
for j in xrange(dimens[1]):
|
for j in xrange(dimens[1]):
|
||||||
elem = _list[i][j]
|
elem = _list[i][j]
|
||||||
@@ -96,7 +102,7 @@ def process_list_image(_list):
|
|||||||
if data_type == float:
|
if data_type == float:
|
||||||
seq_obj.append((int(elem[0] * 255), int(elem[1] * 255), int(elem[2] * 255)))
|
seq_obj.append((int(elem[0] * 255), int(elem[1] * 255), int(elem[2] * 255)))
|
||||||
else:
|
else:
|
||||||
seq_obj.append(elem[0:3])
|
seq_obj.append(tuple(elem[0:3]))
|
||||||
elif data_type == float:
|
elif data_type == float:
|
||||||
#Grayscale 0 - 1.0f
|
#Grayscale 0 - 1.0f
|
||||||
seq_obj.append((int(elem * 255), ) * 3)
|
seq_obj.append((int(elem * 255), ) * 3)
|
||||||
@@ -105,6 +111,6 @@ def process_list_image(_list):
|
|||||||
seq_obj.append((elem, ) * 3)
|
seq_obj.append((elem, ) * 3)
|
||||||
|
|
||||||
#Needs to be 0 - 255 in flattened list of (R, G, B)
|
#Needs to be 0 - 255 in flattened list of (R, G, B)
|
||||||
outImage.putdata(data = seq_obj)
|
out_image.putdata(data = seq_obj)
|
||||||
|
|
||||||
return outImage
|
return out_image
|
||||||
|
|||||||
+81
-1
@@ -291,6 +291,14 @@ class FullAPIRun(unittest.TestCase):
|
|||||||
self.assertEqual(len(response), 48)
|
self.assertEqual(len(response), 48)
|
||||||
self.check_range(response)
|
self.check_range(response)
|
||||||
|
|
||||||
|
def test_rgba_int_array_facial_features(self):
|
||||||
|
test_face = generate_rgba_int_array((48, 48))
|
||||||
|
response = facial_features(test_face)
|
||||||
|
|
||||||
|
self.assertTrue(isinstance(response, list))
|
||||||
|
self.assertEqual(len(response), 48)
|
||||||
|
self.check_range(response)
|
||||||
|
|
||||||
def test_good_int_array_facial_features(self):
|
def test_good_int_array_facial_features(self):
|
||||||
fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy'])
|
fer_set = set(['Angry', 'Sad', 'Neutral', 'Surprise', 'Fear', 'Happy'])
|
||||||
test_face = generate_int_array((48,48))
|
test_face = generate_int_array((48,48))
|
||||||
@@ -421,6 +429,75 @@ class FullAPIRun(unittest.TestCase):
|
|||||||
|
|
||||||
config.api_key = temp_api_key
|
config.api_key = temp_api_key
|
||||||
|
|
||||||
|
|
||||||
|
class NumpyImagesRun(FullAPIRun):
|
||||||
|
"""
|
||||||
|
Testing numpy array as images
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
self.api_key = config.api_key
|
||||||
|
try:
|
||||||
|
import numpy as np
|
||||||
|
globals()["np"] = np
|
||||||
|
except ImportError:
|
||||||
|
self.skipTest("Numpy is not installed!")
|
||||||
|
|
||||||
|
def test_float_numpy_arrays(self):
|
||||||
|
test_image = np.random.random(size=(48,48))
|
||||||
|
response = image_features(test_image)
|
||||||
|
|
||||||
|
self.assertTrue(isinstance(response, list))
|
||||||
|
self.assertEqual(len(response), 2048)
|
||||||
|
self.check_range(response)
|
||||||
|
|
||||||
|
def test_float_RGB_numpy_arrays(self):
|
||||||
|
test_image = np.random.random(size=(48,48,3))
|
||||||
|
response = image_features(test_image)
|
||||||
|
|
||||||
|
self.assertTrue(isinstance(response, list))
|
||||||
|
self.assertEqual(len(response), 2048)
|
||||||
|
self.check_range(response)
|
||||||
|
|
||||||
|
def test_float_RGBA_numpy_arrays(self):
|
||||||
|
test_image = np.random.random(size=(48,48,4))
|
||||||
|
response = image_features(test_image)
|
||||||
|
|
||||||
|
self.assertTrue(isinstance(response, list))
|
||||||
|
self.assertEqual(len(response), 2048)
|
||||||
|
self.check_range(response)
|
||||||
|
|
||||||
|
def test_int_numpy_arrays(self):
|
||||||
|
test_image = np.random.randint(0, 255, size=(48,48))
|
||||||
|
response = image_features(test_image)
|
||||||
|
|
||||||
|
self.assertTrue(isinstance(response, list))
|
||||||
|
self.assertEqual(len(response), 2048)
|
||||||
|
self.check_range(response)
|
||||||
|
|
||||||
|
def test_int_RGB_numpy_arrays(self):
|
||||||
|
test_image = np.random.randint(0, 255, size=(48,48, 3))
|
||||||
|
response = image_features(test_image)
|
||||||
|
|
||||||
|
self.assertTrue(isinstance(response, list))
|
||||||
|
self.assertEqual(len(response), 2048)
|
||||||
|
self.check_range(response)
|
||||||
|
|
||||||
|
def test_int_RGBA_numpy_arrays(self):
|
||||||
|
test_image = np.random.randint(0, 255, size=(48,48, 3))
|
||||||
|
response = image_features(test_image)
|
||||||
|
|
||||||
|
self.assertTrue(isinstance(response, list))
|
||||||
|
self.assertEqual(len(response), 2048)
|
||||||
|
self.check_range(response)
|
||||||
|
|
||||||
|
def test_invalid_int_numpy_arrays(self):
|
||||||
|
test_image = np.random.randint(255, 300, size=(48,48, 3))
|
||||||
|
self.assertRaises(IndicoError, image_features, test_image)
|
||||||
|
|
||||||
|
def test_invalid_int_numpy_arrays(self):
|
||||||
|
test_image = np.random.randint(255, 300, size=(48,48, 5))
|
||||||
|
self.assertRaises(IndicoError, image_features, test_image)
|
||||||
|
|
||||||
def flatten(container):
|
def flatten(container):
|
||||||
for i in container:
|
for i in container:
|
||||||
if isinstance(i, list) or isinstance(i, tuple):
|
if isinstance(i, list) or isinstance(i, tuple):
|
||||||
@@ -433,7 +510,10 @@ def generate_array(size):
|
|||||||
return [[random.random() for _ in xrange(size[0])] for _ in xrange(size[1])]
|
return [[random.random() for _ in xrange(size[0])] for _ in xrange(size[1])]
|
||||||
|
|
||||||
def generate_int_array(size):
|
def generate_int_array(size):
|
||||||
return [[random.randint(0, 50) for _ in xrange(size[0])] for _ in xrange(size[1])]
|
return [[random.randint(0, 255) for _ in xrange(size[0])] for _ in xrange(size[1])]
|
||||||
|
|
||||||
|
def generate_rgba_int_array(size):
|
||||||
|
return [[[random.randint(0, 255) for _ in xrange(3)] for _ in xrange(size[0])] for _ in xrange(size[1])]
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user