diff --git a/.eggs/README.txt b/.eggs/README.txt new file mode 100644 index 0000000..5d01668 --- /dev/null +++ b/.eggs/README.txt @@ -0,0 +1,6 @@ +This directory contains eggs that were downloaded by setuptools to build, test, and run plug-ins. + +This directory caches those eggs to prevent repeated downloads. + +However, it is safe to delete this directory. + diff --git a/indicoio/images/filtering.py b/indicoio/images/filtering.py index 3851b8f..3eb697b 100644 --- a/indicoio/images/filtering.py +++ b/indicoio/images/filtering.py @@ -24,6 +24,6 @@ def content_filtering(image, cloud=None, batch=False, api_key=None, **kwargs): :type image: list of lists :rtype: float of nsfwness """ - image = image_preprocess(image, batch=batch, size=None) + image = image_preprocess(image, batch=batch, size=None, min_axis=128) url_params = {"batch": batch, "api_key": api_key} return api_handler(image, cloud=cloud, api="contentfiltering", url_params=url_params, **kwargs) diff --git a/indicoio/utils/image.py b/indicoio/utils/image.py index 29b3312..8db17d7 100644 --- a/indicoio/utils/image.py +++ b/indicoio/utils/image.py @@ -10,7 +10,7 @@ from indicoio.utils.errors import IndicoError, DataStructureException B64_PATTERN = re.compile("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)") -def image_preprocess(image, size=(48,48), batch=False): +def image_preprocess(image, size=(48,48), min_axis=None, batch=False): """ Takes an image and prepares it for sending to the api including resizing and image data/structure standardizing. @@ -41,9 +41,7 @@ def image_preprocess(image, size=(48,48), batch=False): else: raise IndicoError("Image must be a filepath, base64 encoded string, or a numpy array") - # image resizing - if size: - out_image = out_image.resize(size) + out_image = resize_image(out_image, size, min_axis) # convert to base64 temp_output = StringIO.StringIO() @@ -54,6 +52,25 @@ def image_preprocess(image, size=(48,48), batch=False): return base64.b64encode(output_s) +def resize_image(image, size, min_axis): + if size: + image = image.resize(size) + if min_axis: + min_idx, other_idx = (0,1) if image.size[0] < image.size[1] else (1,0) + aspect = image.size[other_idx]/float(image.size[min_idx]) + if aspect > 10: + warnings.warn( + "An aspect ratio greater than 10:1 is not recommended", + Warning + ) + size_arr = [0,0] + size_arr[min_idx] = min_axis + size_arr[other_idx] = int(min_axis * aspect) + image = image.resize(tuple(size_arr)) + + return image + + def get_list_dimensions(_list): """ Takes a nested list and returns the size of each dimension followed diff --git a/tests/test_remote.py b/tests/test_remote.py index 5fe482f..f41f31a 100644 --- a/tests/test_remote.py +++ b/tests/test_remote.py @@ -336,6 +336,11 @@ class FullAPIRun(unittest.TestCase): response = content_filtering(test_face) self.assertTrue(response < 0.5) + def test_resize_content_filtering(self): + test_face = os.path.normpath(os.path.join(DIR, "data/happy.png")) + response = content_filtering(test_face) + self.assertTrue(isinstance(response, float)) + def test_good_facial_features(self): test_face = os.path.normpath(os.path.join(DIR, "data/48by48.png")) response = facial_features(test_face) @@ -551,6 +556,11 @@ class NumpyImagesRun(FullAPIRun): test_image = np.random.randint(255, 300, size=(48,48, 5)) self.assertRaises(IndicoError, image_features, test_image) + def test_resize_content_filtering_numpy_arrays(self): + test_image = np.random.randint(0, 255, size=(480,248, 3)) + response = content_filtering(test_image) + self.assertTrue(isinstance(response, float)) + def flatten(container): for i in container: if isinstance(i, list) or isinstance(i, tuple): diff --git a/tests/unit_test.py b/tests/unit_test.py new file mode 100644 index 0000000..437c62e --- /dev/null +++ b/tests/unit_test.py @@ -0,0 +1,16 @@ +from indicoio.utils.image import image_preprocess +from PIL import Image +import os, unittest, base64, StringIO + +DIR = os.path.dirname(os.path.realpath(__file__)) + +class ResizeTests(unittest.TestCase): + """ + test image resizing + """ + def test_min_axis_resize(self): + test_image = os.path.normpath(os.path.join(DIR, "data/fear.png")) + resized_image = image_preprocess(test_image, min_axis=360) + image_string = StringIO.StringIO(base64.b64decode(resized_image)) + image = Image.open(image_string) + self.assertEqual(image.size, (360.0, 360.0))