From c4f0a80ecbf2546827a444d19a12d59945a9deab Mon Sep 17 00:00:00 2001 From: Karthik Muthuraman Date: Thu, 11 Jul 2019 11:03:48 -0700 Subject: [PATCH] Image Utils (#13) * Initial commit * initial commit. * Add backbone for image_utils module. Also updated the setup.py file with the Pillow dependency. * Added basic image pre processing utils. * Added postprocessor code. * added test image and code. modularized preprocessing. * Changed variable names to avoid confusion. * Fixed postprocessing code. * Rename test_temp.py and add pytest, add verbosity support, and reformat * Added functions for converting dtype and standardize/normalize. * Switch to ABC structure, implement sanity checks, implement more transformations, and add some tests * Update dimension checks, and add denormalization * add documentation * rearranged functions and other cosmetic changes. * Fixed function signature in test script. * Fixed issues from unit testing. * fixed typo. Co-Authored-By: kmh4321 * Updated test scripts. * added individual test cases. * Removed ABC. * Removed DS_Store. * Fixed pytest duplicate test calls. * Fix travis CI flake issues. * Fixes travis issues. * Fixes travis issues. * Fixes travis issues. * WIP image utils rework * WIP image utils rework * added various tests, fixed some bugs, and implement standardize, normalize, rotate * add flask error support * add another layer to specifically customize error messages * Fix flake8 issues. * Fixed pytest error. * Create a MAXImageProcessor and a regular ImageProcessor * Propose move of MAXImageProcessor to `core/api.py` * move to utils.py folder * rewrite MAXImageProcessor and update tests * [wip] updates nick * Fix bug in standardize and normalize, enforce proper use and write corresponding tests * add extra test for rotation * add grayscale value tests and general image value bounds * add more pixel value tests * updates hong: add documentation for `apply transforms`, remove unused variable, and restructure tests` * comments hong: further optimize tests and add documentation * comments gitignore hong * extend standardize functionality * update standardize exceptions. * Fix flake8 linting issue. * feedback Nick * Added specific flask exceptions. * Flask exception handing. * flake8. * Added license headers. * flask error messages. * prohibit standardization of RGBA images --- .gitignore | 8 +- .travis.yml | 2 +- maxfw/__init__.py | 15 + maxfw/core/__init__.py | 16 + maxfw/core/api.py | 15 + maxfw/core/app.py | 15 + maxfw/core/default_config.py | 15 + maxfw/core/utils.py | 61 ++++ maxfw/model/__init__.py | 15 + maxfw/model/model.py | 16 + maxfw/tests/__init__.py | 15 + maxfw/tests/test_image.jpg | Bin 0 -> 139867 bytes maxfw/tests/test_image_utils.py | 382 ++++++++++++++++++++++ maxfw/utils/__init__.py | 15 + maxfw/utils/image_functions.py | 542 ++++++++++++++++++++++++++++++++ maxfw/utils/image_utils.py | 240 ++++++++++++++ setup.py | 20 +- 17 files changed, 1389 insertions(+), 3 deletions(-) create mode 100644 maxfw/__init__.py create mode 100644 maxfw/core/utils.py create mode 100644 maxfw/tests/__init__.py create mode 100644 maxfw/tests/test_image.jpg create mode 100644 maxfw/tests/test_image_utils.py create mode 100644 maxfw/utils/__init__.py create mode 100644 maxfw/utils/image_functions.py create mode 100644 maxfw/utils/image_utils.py diff --git a/.gitignore b/.gitignore index 4ad6467..3be13a2 100644 --- a/.gitignore +++ b/.gitignore @@ -103,4 +103,10 @@ venv.bak/ # mypy .mypy_cache/ -.idea/ \ No newline at end of file +# local test files +test_image_utils/ +.idea/ + +# other +*.DS_Store +.vscode/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index b7ccd06..71913d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,7 +15,7 @@ install: before_script: - flake8 . --max-line-length=127 script: - - true # add other tests here + - python setup.py test # add other tests here notifications: on_success: change on_failure: change # `always` will be the setting once code changes slow down diff --git a/maxfw/__init__.py b/maxfw/__init__.py new file mode 100644 index 0000000..487277e --- /dev/null +++ b/maxfw/__init__.py @@ -0,0 +1,15 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# diff --git a/maxfw/core/__init__.py b/maxfw/core/__init__.py index 81cf59c..db0f077 100644 --- a/maxfw/core/__init__.py +++ b/maxfw/core/__init__.py @@ -1,2 +1,18 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# from .app import MAXApp, MAX_API # noqa from .api import * # noqa +from .utils import * # noqa diff --git a/maxfw/core/api.py b/maxfw/core/api.py index 8d03d82..2b7505c 100644 --- a/maxfw/core/api.py +++ b/maxfw/core/api.py @@ -1,3 +1,18 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# from .app import MAX_API from flask_restplus import Resource, fields diff --git a/maxfw/core/app.py b/maxfw/core/app.py index 5df0ec9..8060d3f 100644 --- a/maxfw/core/app.py +++ b/maxfw/core/app.py @@ -1,3 +1,18 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# import os from flask import Flask from flask_restplus import Api, Namespace diff --git a/maxfw/core/default_config.py b/maxfw/core/default_config.py index 5e93617..d85a3e1 100644 --- a/maxfw/core/default_config.py +++ b/maxfw/core/default_config.py @@ -1,3 +1,18 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# # API metadata API_TITLE = 'Model Asset Exchange Microservice' API_DESC = 'An API for serving models' diff --git a/maxfw/core/utils.py b/maxfw/core/utils.py new file mode 100644 index 0000000..7c110b5 --- /dev/null +++ b/maxfw/core/utils.py @@ -0,0 +1,61 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# +from flask import abort +from maxfw.utils.image_utils import ImageProcessor + + +def redirect_errors_to_flask(func): + """ + This decorator function will capture all Pythonic errors and return them as flask errors. + + If you are looking to disable this functionality, please remove this decorator from the `apply_transforms()` module + under the ImageProcessor class. + """ + + def inner(*args, **kwargs): + try: + # run the function + return func(*args, **kwargs) + except ValueError as ve: + if 'pic should be 2 or 3 dimensional' in str(ve): + abort(400, "Invalid input, please ensure the input is either " + "a grayscale or a colour image.") + except TypeError as te: + if 'bytes or ndarray' in str(te): + abort(400, "Invalid input format, please make sure the input file format " + " is a common image format such as JPG or PNG.") + return inner + + +class MAXImageProcessor(ImageProcessor): + """Composes several transforms together. + + Args: + transforms (list of ``Transform`` objects): list of transforms to compose. + + Example: + >>> pipeline = ImageProcessor([ + >>> Rotate(150), + >>> Resize([100,100]) + >>> ]) + >>> pipeline.apply_transforms(img) + """ + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + @redirect_errors_to_flask + def apply_transforms(self, img): + return super().apply_transforms(img) diff --git a/maxfw/model/__init__.py b/maxfw/model/__init__.py index 3d20c4b..fce5430 100644 --- a/maxfw/model/__init__.py +++ b/maxfw/model/__init__.py @@ -1 +1,16 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# from .model import MAXModelWrapper # noqa diff --git a/maxfw/model/model.py b/maxfw/model/model.py index d7f6a65..f4f04b0 100644 --- a/maxfw/model/model.py +++ b/maxfw/model/model.py @@ -1,3 +1,19 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# + from abc import ABC, abstractmethod diff --git a/maxfw/tests/__init__.py b/maxfw/tests/__init__.py new file mode 100644 index 0000000..487277e --- /dev/null +++ b/maxfw/tests/__init__.py @@ -0,0 +1,15 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# diff --git a/maxfw/tests/test_image.jpg b/maxfw/tests/test_image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6311aa8fd9141ede2f6f9c12a69f67d6c4f4e656 GIT binary patch literal 139867 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 EKiUmrssI20 literal 0 HcmV?d00001 diff --git a/maxfw/tests/test_image_utils.py b/maxfw/tests/test_image_utils.py new file mode 100644 index 0000000..9e37f86 --- /dev/null +++ b/maxfw/tests/test_image_utils.py @@ -0,0 +1,382 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# +# Standard libs +import io + +# Dependencies +import nose +import numpy as np +from PIL import Image + +# The module to test +from maxfw.utils.image_utils import ImageProcessor, ToPILImage, Resize, Grayscale, Normalize, Standardize, Rotate, \ + PILtoarray +from maxfw.core.utils import MAXImageProcessor + +# Initialize a test input file +stream = io.BytesIO() +Image.open('maxfw/tests/test_image.jpg').convert('RGBA').save(stream, 'PNG') +test_input = stream.getvalue() + + +def test_imageprocessor_read(): + """Test the Imageprocessor.""" + + # Test with 4 channels + transform_sequence = [ToPILImage('RGBA')] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (678, 1024, 4) + + # Test with 3 channels + transform_sequence = [ToPILImage('RGB')] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (678, 1024, 3) + + # Test the values of the image + transform_sequence = [ToPILImage('RGBA'), PILtoarray()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.min(img_out) >= 0 + assert np.max(img_out) <= 255 + + # Test the values of the image + transform_sequence = [ToPILImage('L'), PILtoarray()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.min(img_out) >= 0 + assert np.max(img_out) <= 255 + + +def test_imageprocessor_resize(): + """Test the Imageprocessor's resize function.""" + + # Resize to 200x200 + transform_sequence = [ToPILImage('RGBA'), Resize(size=(200, 200))] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 4) + + # Resize to 2000x2000 + transform_sequence = [ToPILImage('RGBA'), Resize(size=(2000, 2000))] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (2000, 2000, 4) + + +def test_imageprocessor_grayscale(): + """Test the Imageprocessor's grayscale function.""" + + # Using the standard 1 output channel + transform_sequence = [ToPILImage('RGBA'), Resize(size=(200, 200)), Grayscale()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200) + + # Using 3 output channels + transform_sequence = [ToPILImage('RGBA'), Resize(size=(200, 200)), Grayscale(num_output_channels=3)] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 3) + + # Using 4 output channels + transform_sequence = [ToPILImage('RGBA'), Resize(size=(200, 200)), Grayscale(num_output_channels=4), PILtoarray()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert img_out.shape == (200, 200, 4) + + # Test that the values in all 4 output channels are identical + assert img_out[..., 0].all() == img_out[..., 1].all() == img_out[..., 2].all() == img_out[..., 3].all() + + +def test_imageprocessor_normalize(): + """Test the Imageprocessor's normalize function.""" + + # Test normalize + transform_sequence = [ToPILImage('RGBA'), Normalize()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.max(img_out) <= 1 and np.min(img_out) >= 0 + + # Test normalize + transform_sequence = [ToPILImage('RGB'), Normalize()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.max(img_out) <= 1 and np.min(img_out) >= 0 + + # Test normalize + transform_sequence = [ToPILImage('L'), Normalize()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.max(img_out) <= 1 and np.min(img_out) >= 0 + + # Test for wrong use + transform_sequence = [ToPILImage('L'), Normalize(), Resize(size=(200, 200))] + p = ImageProcessor(transform_sequence) + with nose.tools.assert_raises(Exception): + p.apply_transforms(test_input) + + # Test for wrong use + transform_sequence = [ToPILImage('RGBA'), Normalize(), Normalize()] + p = ImageProcessor(transform_sequence) + with nose.tools.assert_raises(Exception): + p.apply_transforms(test_input) + + +def test_imageprocessor_standardize(): + """Test the Imageprocessor's standardize function.""" + + # Test standardize (RGBA) + # The `A` channel cannot be standardized, and will therefore prompt an error message when attempted. + transform_sequence = [ToPILImage('RGBA'), Standardize()] + with nose.tools.assert_raises_regexp(AssertionError, r".*must be converted to an image with 3 or fewer channels.*"): + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (RGB) + transform_sequence = [ToPILImage('RGB'), Standardize()] + p = ImageProcessor(transform_sequence) + img_out = np.array(p.apply_transforms(test_input)) + nose.tools.assert_almost_equal(np.std(img_out), 1) + nose.tools.assert_almost_equal(np.mean(img_out), 0) + + # Test standardize (RGB) - check whether the mean centering works + transform_sequence = [ToPILImage('RGB'), Standardize(std=0)] + p = ImageProcessor(transform_sequence) + img_out = np.array(p.apply_transforms(test_input)) + nose.tools.assert_almost_equal(np.mean(img_out), 0) + + # Test standardize (RGB) - check whether the std division works + transform_sequence = [ToPILImage('RGB'), Standardize(mean=0)] + p = ImageProcessor(transform_sequence) + img_out = np.array(p.apply_transforms(test_input)) + nose.tools.assert_almost_equal(np.std(img_out[..., 0]), 1) + nose.tools.assert_almost_equal(np.std(img_out[..., 1]), 1) + nose.tools.assert_almost_equal(np.std(img_out[..., 2]), 1) + + # generate an image array + pil_img = ImageProcessor([ToPILImage('RGB'), PILtoarray()]).apply_transforms(test_input) + + # Test standardize (RGB) with 3 channel-wise values + transform_sequence = [ToPILImage('RGB'), Standardize(mean=[x for x in np.mean(pil_img, axis=(0, 1))], + std=[x for x in np.std(pil_img, axis=(0, 1))])] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (RGB) with 3 channel-wise values for the mean + transform_sequence = [ToPILImage('RGB'), Standardize(mean=[x for x in np.mean(pil_img, axis=(0, 1))])] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (RGB) with 3 channel-wise values for the std + transform_sequence = [ToPILImage('RGB'), Standardize(std=[x for x in np.std(pil_img, axis=(0, 1))])] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (RGB) + transform_sequence = [ToPILImage('RGB'), Standardize(mean=np.mean(pil_img))] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (RGB) + transform_sequence = [ToPILImage('RGB'), Standardize(mean=np.mean(pil_img), std=np.std(pil_img))] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (RGB) + transform_sequence = [ToPILImage('RGB'), Standardize(std=np.std(pil_img))] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (RGB) + transform_sequence = [ToPILImage('RGB'), Standardize(mean=127, std=5)] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize error (RGB) + transform_sequence = [ToPILImage('RGB'), Standardize(mean=[127, 127], std=5)] + with nose.tools.assert_raises_regexp(AssertionError, r".*must correspond to the number of channels.*"): + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize error (RGB) + transform_sequence = [ToPILImage('RGB'), Standardize(std=[5, 5, 5, 5])] + with nose.tools.assert_raises_regexp(AssertionError, r".*must correspond to the number of channels.*"): + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (L) + transform_sequence = [ToPILImage('L'), Standardize()] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + nose.tools.assert_almost_equal(np.std(img_out), 1) + + # Test standardize (L) + transform_sequence = [ToPILImage('L'), Standardize(mean=np.mean(pil_img))] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (L) + transform_sequence = [ToPILImage('L'), Standardize(mean=np.mean(pil_img), std=np.std(pil_img))] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (L) + transform_sequence = [ToPILImage('L'), Standardize(std=np.std(pil_img))] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (L) + transform_sequence = [ToPILImage('L'), Standardize(mean=127, std=5)] + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize (L) - check whether the mean centering works + transform_sequence = [ToPILImage('L'), Standardize(std=0)] + p = ImageProcessor(transform_sequence) + img_out = np.array(p.apply_transforms(test_input)) + nose.tools.assert_almost_equal(np.mean(img_out), 0) + + # Test standardize (L) - check whether the std division works + transform_sequence = [ToPILImage('L'), Standardize(mean=0)] + p = ImageProcessor(transform_sequence) + img_out = np.array(p.apply_transforms(test_input)) + nose.tools.assert_almost_equal(np.std(img_out), 1) + + # Test standardize error (L) + transform_sequence = [ToPILImage('L'), Standardize(mean=[127, 127], std=5)] + with nose.tools.assert_raises(AssertionError): + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test standardize error (L) + transform_sequence = [ToPILImage('L'), Standardize(std=[5, 5, 5, 5])] + with nose.tools.assert_raises(AssertionError): + ImageProcessor(transform_sequence).apply_transforms(test_input) + + # Test for wrong use (L) + transform_sequence = [ToPILImage('L'), Standardize(), Resize(size=(200, 200))] + p = ImageProcessor(transform_sequence) + with nose.tools.assert_raises(Exception): + p.apply_transforms(test_input) + + # Test for wrong use (RGBA) + transform_sequence = [ToPILImage('RGBA'), Standardize(), Standardize()] + p = ImageProcessor(transform_sequence) + with nose.tools.assert_raises(Exception): + p.apply_transforms(test_input) + + +def test_imageprocessor_rotate(): + """Test the Imageprocessor's rotate function.""" + + # Test rotate (int) + transform_sequence = [ToPILImage('RGBA'), Resize((200, 200)), Rotate(5)] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 4) + + # Test rotate vs Pillow rotate + transform_sequence = [ToPILImage('RGBA'), Resize((200, 200))] + p = ImageProcessor(transform_sequence) + img_in = p.apply_transforms(test_input) + + transform_sequence = [Rotate(5)] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(img_in) + assert img_in.rotate(5) == img_out + + # Test rotate (negative int) + transform_sequence = [ToPILImage('RGBA'), Resize((200, 200)), Rotate(-5)] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 4) + + # Test rotate (float) + transform_sequence = [ToPILImage('RGBA'), Resize((200, 200)), Rotate(499.99)] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 4) + + +def test_imageprocessor_combinations(): + """Test various combinations of the Imageprocessor's functionality.""" + + # Combination 1 + transform_sequence = [ + ToPILImage('RGB'), + Resize((2000, 2000)), + Rotate(5), + Grayscale(num_output_channels=4), + Resize((200, 200)), + Normalize() + ] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 4) + + # Combination 2 + transform_sequence = [ + ToPILImage('RGB'), + Resize((200, 200)), + Normalize() + ] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 3) + + # Combination 3 + transform_sequence = [ + ToPILImage('RGB'), + Resize((200, 200)), + Standardize() + ] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert np.array(img_out).shape == (200, 200, 3) + + # Combination 5 - including pixel value tests + transform_sequence = [ + ToPILImage('RGB'), + Resize((2000, 2000)), + Rotate(5), + Grayscale(num_output_channels=4), + Resize((200, 200)), + PILtoarray() + ] + p = ImageProcessor(transform_sequence) + img_out = p.apply_transforms(test_input) + assert img_out.shape == (200, 200, 4) + assert np.min(img_out) >= 0 + assert np.max(img_out) <= 255 + + # Combination 6 - utilize the pipeline multiple times + transform_sequence = [ + ToPILImage('RGB'), + Resize((2000, 2000)), + Rotate(5), + Grayscale(num_output_channels=4), + Resize((200, 200)), + PILtoarray() + ] + p = ImageProcessor(transform_sequence) + p.apply_transforms(test_input) + p.apply_transforms(test_input) + + +def test_flask_error(): + + # Test invalid input format + transform_sequence = [ToPILImage('RGB')] + p = MAXImageProcessor(transform_sequence) + with nose.tools.assert_raises_regexp(Exception, r".*Invalid input format*"): + p.apply_transforms("") + + # Test invalid input dimensions + transform_sequence = [ToPILImage('RGB')] + p = MAXImageProcessor(transform_sequence) + with nose.tools.assert_raises_regexp(Exception, r".*grayscale or a colour image*"): + p.apply_transforms(np.random.rand(10, 10, 10, 10)) + + +if __name__ == '__main__': + nose.main() diff --git a/maxfw/utils/__init__.py b/maxfw/utils/__init__.py new file mode 100644 index 0000000..487277e --- /dev/null +++ b/maxfw/utils/__init__.py @@ -0,0 +1,15 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# diff --git a/maxfw/utils/image_functions.py b/maxfw/utils/image_functions.py new file mode 100644 index 0000000..b7c6151 --- /dev/null +++ b/maxfw/utils/image_functions.py @@ -0,0 +1,542 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# +from __future__ import division +import sys +import io +import numbers +import collections + +from PIL import Image, ImageEnhance +import numpy as np + +if sys.version_info < (3, 3): + Sequence = collections.Sequence + Iterable = collections.Iterable +else: + Sequence = collections.abc.Sequence + Iterable = collections.abc.Iterable + + +def _is_pil_image(img): + return isinstance(img, Image.Image) + + +def _is_numpy_image(img): + return isinstance(img, np.ndarray) and (img.ndim in {2, 3}) + + +def to_pil_image(pic, target_mode, mode=None): + """Convert an ndarray to PIL Image. + + Args: + pic (io.BytesIO or numpy.ndarray): Image to be converted to PIL Image. + mode (`PIL.Image mode`_): color space and pixel depth of input data (optional). + + .. _PIL.Image mode: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#concept-modes + + Returns: + PIL Image: Image converted to PIL Image. + """ + if not isinstance(pic, (bytes, bytearray)) and not(isinstance(pic, np.ndarray)): + # if the object is not bytes, and it's not a ndarray + raise TypeError('pic should be bytes or ndarray. Got {}.'.format(type(pic))) + + elif isinstance(pic, np.ndarray): + if pic.ndim not in {2, 3}: + raise ValueError('pic should be 2 or 3 dimensional. Got {} dimensions.'.format(pic.ndim)) + + elif pic.ndim == 2: + # if 2D image, add channel dimension (HWC) + pic = np.expand_dims(pic, 2) + + elif isinstance(pic, (bytes, bytearray)): + try: + # verify that the object can be loaded into memory + pic = np.array(Image.open(io.BytesIO(pic))) + except Exception: + raise TypeError('The input bytes object is not suitable for the Pillow library. Check the input again.') + + npimg = pic + if not isinstance(npimg, np.ndarray): + raise TypeError('Input pic must be a bytes object or NumPy ndarray, ' + + 'not {}'.format(type(npimg))) + + if npimg.shape[2] == 1: + expected_mode = None + npimg = npimg[:, :, 0] + if npimg.dtype == np.uint8: + expected_mode = 'L' + elif npimg.dtype == np.int16: + expected_mode = 'I;16' + elif npimg.dtype == np.int32: + expected_mode = 'I' + elif npimg.dtype == np.float32: + expected_mode = 'F' + if mode is not None and mode != expected_mode: + raise ValueError("Incorrect mode ({}) supplied for input type {}. Should be {}" + .format(mode, np.dtype, expected_mode)) + mode = expected_mode + + elif npimg.shape[2] == 2: + permitted_2_channel_modes = ['LA'] + if mode is not None and mode not in permitted_2_channel_modes: + raise ValueError("Only modes {} are supported for 2D inputs".format(permitted_2_channel_modes)) + + if mode is None and npimg.dtype == np.uint8: + mode = 'LA' + + elif npimg.shape[2] == 4: + permitted_4_channel_modes = ['RGBA', 'CMYK', 'RGBX'] + if mode is not None and mode not in permitted_4_channel_modes: + raise ValueError("Only modes {} are supported for 4D inputs".format(permitted_4_channel_modes)) + + if mode is None and npimg.dtype == np.uint8: + mode = 'RGBA' + else: + permitted_3_channel_modes = ['RGB', 'YCbCr', 'HSV'] + if mode is not None and mode not in permitted_3_channel_modes: + raise ValueError("Only modes {} are supported for 3D inputs".format(permitted_3_channel_modes)) + if mode is None and npimg.dtype == np.uint8: + mode = 'RGB' + + if mode is None: + raise TypeError('Input type {} is not supported'.format(npimg.dtype)) + + # Verify that the target mode exists + assert target_mode in [1, 'L', 'P', 'RGB', 'RGBA', 'CMYK', 'YCbCr', 'LAB', 'HSV', 'I', 'F', 'RGBX', 'RGBBa'] + + return Image.fromarray(npimg, mode=mode).convert(target_mode) + + +def pil_to_array(pic): + assert _is_pil_image(pic), 'The input image for `PILtoarray` is not a PIL Image object.' + return np.array(pic) + + +def normalize(img): + if type(img) is not np.ndarray: + img = np.array(img) + return img / (np.max(img) - np.min(img)) + + +def standardize(img, mean=None, std=None): + # ensure we are working with a numpy ndarray + if type(img) is not np.ndarray: + img = np.array(img) + img = img.astype(np.float64) + + # check whether the image has channels + if img.ndim == 3: + # (this image has channels) + # calculate the number of channels + channels = img.shape[-1] + assert channels < 4, 'An image with more than 3 channels, ' \ + 'e.g. `RGBA`, must be converted to an image with 3 or fewer channels (e.g. `RGB` or `L`)' \ + 'before it can be standardized correctly.' + + if mean is None: + # calculate channel-wise mean + mean = np.mean(img, axis=(0, 1), keepdims=True) + elif isinstance(mean, (int, float)): + # convert the number to an array + mean = np.array([mean] * channels).reshape((1, 1, channels)) + elif isinstance(mean, Sequence): + # convert a sequence to the right dimensions + assert np.sum([not isinstance(x, (int, float)) for x in mean]) == 0, \ + 'The sequence `mean` can only contain numbers.' + assert len(mean) == channels, \ + 'The size of the `mean` array must correspond to the number of channels in the image.' + mean = np.array(mean).reshape((1, 1, channels)) + else: + # if the mean is not a number or a sequence + raise TypeError('`Mean` should either be a number or an n-dimensional vector of numbers ' + 'with n equal to the number of image channels.') + + if std is None: + # calculate channel-wise std + std = np.std(img, axis=(0, 1)).reshape((channels,)) + elif isinstance(std, (int, float)): + # convert the number to an array + std = np.array([std] * channels).reshape((channels,)) + elif isinstance(std, Sequence): + # convert a sequence to the right dimensions + assert np.sum([not isinstance(x, (int, float)) for x in std]) == 0, \ + 'The sequence `std` can only contain numbers.' + assert len(std) == channels, \ + 'The size of the `std` array must correspond to the number of channels in the image.' + std = np.array(std).reshape((channels,)) + else: + # if the std is not a number or a sequence + raise TypeError('`std` should either be a number or an n-dimensional vector ' + 'of numbers with n equal to the number of image channels.') + + # return the standardized array + # a. mean center + img_mean_centered = (img - mean).astype(np.float64) + + # b. channel-wise division by std + for c in range(channels): + if std[c] != 0: + img_mean_centered[..., c] = img_mean_centered[..., c] / std[c] + + return img_mean_centered + + else: + # (this image has no channels) + if mean is None: + mean = np.mean(img) + elif isinstance(mean, Sequence): + assert len(mean) == 1 + mean = mean[0] + elif not isinstance(mean, (int, float)): + raise ValueError('The value for `mean` should be a number or `None` ' + 'when working with single-channel images.') + + if std is None: + std = np.std(img) + elif isinstance(std, Sequence): + assert len(std) == 1 + std = std[0] + elif not isinstance(std, (int, float)): + raise ValueError('The value for `std` should be a number or `None` ' + 'when working with single-channel images.') + + if std != 0: + return (img-mean)/std + else: + return img-mean + + +def resize(img, size, interpolation=Image.BILINEAR): + r"""Resize the input PIL Image to the given size. + + Args: + img (PIL Image): Image to be resized. + size (sequence or int): Desired output size. If size is a sequence like + (h, w), the output size will be matched to this. If size is an int, + the smaller edge of the image will be matched to this number maintaing + the aspect ratio. i.e, if height > width, then image will be rescaled to + :math:`\left(\text{size} \times \frac{\text{height}}{\text{width}}, \text{size}\right)` + interpolation (int, optional): Desired interpolation. Default is + ``PIL.Image.BILINEAR`` + + Returns: + PIL Image: Resized image. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + if not (isinstance(size, int) or (isinstance(size, Iterable) and len(size) == 2)): + raise TypeError('Got inappropriate size arg: {}'.format(size)) + + if isinstance(size, int): + w, h = img.size + if (w <= h and w == size) or (h <= w and h == size): + return img + if w < h: + ow = size + oh = int(size * h / w) + return img.resize((ow, oh), interpolation) + else: + oh = size + ow = int(size * w / h) + return img.resize((ow, oh), interpolation) + else: + return img.resize(size[::-1], interpolation) + + +def crop(img, i, j, h, w): + """Crop the given PIL Image. + + Args: + img (PIL Image): Image to be cropped. + i (int): i in (i,j) i.e coordinates of the upper left corner. + j (int): j in (i,j) i.e coordinates of the upper left corner. + h (int): Height of the cropped image. + w (int): Width of the cropped image. + + Returns: + PIL Image: Cropped image. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + return img.crop((j, i, j + w, i + h)) + + +def center_crop(img, output_size): + if isinstance(output_size, numbers.Number): + output_size = (int(output_size), int(output_size)) + w, h = img.size + th, tw = output_size + i = int(round((h - th) / 2.)) + j = int(round((w - tw) / 2.)) + return crop(img, i, j, th, tw) + + +def resized_crop(img, i, j, h, w, size, interpolation=Image.BILINEAR): + """Crop the given PIL Image and resize it to desired size. + + Args: + img (PIL Image): Image to be cropped. + i (int): i in (i,j) i.e coordinates of the upper left corner + j (int): j in (i,j) i.e coordinates of the upper left corner + h (int): Height of the cropped image. + w (int): Width of the cropped image. + size (sequence or int): Desired output size. Same semantics as ``resize``. + interpolation (int, optional): Desired interpolation. Default is + ``PIL.Image.BILINEAR``. + Returns: + PIL Image: Cropped image. + """ + assert _is_pil_image(img), 'img should be PIL Image' + img = crop(img, i, j, h, w) + img = resize(img, size, interpolation) + return img + + +def hflip(img): + """Horizontally flip the given PIL Image. + + Args: + img (PIL Image): Image to be flipped. + + Returns: + PIL Image: Horizontall flipped image. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + return img.transpose(Image.FLIP_LEFT_RIGHT) + + +def vflip(img): + """Vertically flip the given PIL Image. + + Args: + img (PIL Image): Image to be flipped. + + Returns: + PIL Image: Vertically flipped image. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + return img.transpose(Image.FLIP_TOP_BOTTOM) + + +def adjust_brightness(img, brightness_factor): + """Adjust brightness of an Image. + + Args: + img (PIL Image): PIL Image to be adjusted. + brightness_factor (float): How much to adjust the brightness. Can be + any non negative number. 0 gives a black image, 1 gives the + original image while 2 increases the brightness by a factor of 2. + + Returns: + PIL Image: Brightness adjusted image. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + enhancer = ImageEnhance.Brightness(img) + img = enhancer.enhance(brightness_factor) + return img + + +def adjust_contrast(img, contrast_factor): + """Adjust contrast of an Image. + + Args: + img (PIL Image): PIL Image to be adjusted. + contrast_factor (float): How much to adjust the contrast. Can be any + non negative number. 0 gives a solid gray image, 1 gives the + original image while 2 increases the contrast by a factor of 2. + + Returns: + PIL Image: Contrast adjusted image. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + enhancer = ImageEnhance.Contrast(img) + img = enhancer.enhance(contrast_factor) + return img + + +def adjust_saturation(img, saturation_factor): + """Adjust color saturation of an image. + + Args: + img (PIL Image): PIL Image to be adjusted. + saturation_factor (float): How much to adjust the saturation. 0 will + give a black and white image, 1 will give the original image while + 2 will enhance the saturation by a factor of 2. + + Returns: + PIL Image: Saturation adjusted image. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + enhancer = ImageEnhance.Color(img) + img = enhancer.enhance(saturation_factor) + return img + + +def adjust_hue(img, hue_factor): + """Adjust hue of an image. + + The image hue is adjusted by converting the image to HSV and + cyclically shifting the intensities in the hue channel (H). + The image is then converted back to original image mode. + + `hue_factor` is the amount of shift in H channel and must be in the + interval `[-0.5, 0.5]`. + + See `Hue`_ for more details. + + .. _Hue: https://en.wikipedia.org/wiki/Hue + + Args: + img (PIL Image): PIL Image to be adjusted. + hue_factor (float): How much to shift the hue channel. Should be in + [-0.5, 0.5]. 0.5 and -0.5 give complete reversal of hue channel in + HSV space in positive and negative direction respectively. + 0 means no shift. Therefore, both -0.5 and 0.5 will give an image + with complementary colors while 0 gives the original image. + + Returns: + PIL Image: Hue adjusted image. + """ + if not(-0.5 <= hue_factor <= 0.5): + raise ValueError('hue_factor - {} is not in [-0.5, 0.5].'.format(hue_factor)) + + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + input_mode = img.mode + if input_mode in {'L', '1', 'I', 'F'}: + return img + + h, s, v = img.convert('HSV').split() + + np_h = np.array(h, dtype=np.uint8) + # uint8 addition take cares of rotation across boundaries + with np.errstate(over='ignore'): + np_h += np.uint8(hue_factor * 255) + h = Image.fromarray(np_h, 'L') + + img = Image.merge('HSV', (h, s, v)).convert(input_mode) + return img + + +def adjust_gamma(img, gamma, gain=1): + r"""Perform gamma correction on an image. + + Also known as Power Law Transform. Intensities in RGB mode are adjusted + based on the following equation: + + .. math:: + I_{\text{out}} = 255 \times \text{gain} \times \left(\frac{I_{\text{in}}}{255}\right)^{\gamma} + + See `Gamma Correction`_ for more details. + + .. _Gamma Correction: https://en.wikipedia.org/wiki/Gamma_correction + + Args: + img (PIL Image): PIL Image to be adjusted. + gamma (float): Non negative real number, same as :math:`\gamma` in the equation. + gamma larger than 1 make the shadows darker, + while gamma smaller than 1 make dark regions lighter. + gain (float): The constant multiplier. + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + if gamma < 0: + raise ValueError('Gamma should be a non-negative real number') + + input_mode = img.mode + img = img.convert('RGB') + + gamma_map = [255 * gain * pow(ele / 255., gamma) for ele in range(256)] * 3 + img = img.point(gamma_map) # use PIL's point-function to accelerate this part + + img = img.convert(input_mode) + return img + + +def rotate(img, angle, resample=False, expand=False, center=None): + """Rotate the image by angle. + + + Args: + img (PIL Image): PIL Image to be rotated. + angle (float or int): In degrees degrees counter clockwise order. + resample (``PIL.Image.NEAREST`` or ``PIL.Image.BILINEAR`` or ``PIL.Image.BICUBIC``, optional): + An optional resampling filter. See `filters`_ for more information. + If omitted, or if the image has mode "1" or "P", it is set to ``PIL.Image.NEAREST``. + expand (bool, optional): Optional expansion flag. + If true, expands the output image to make it large enough to hold the entire rotated image. + If false or omitted, make the output image the same size as the input image. + Note that the expand flag assumes rotation around the center and no translation. + center (2-tuple, optional): Optional center of rotation. + Origin is the upper left corner. + Default is the center of the image. + + .. _filters: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#filters + + """ + assert isinstance(angle, (int, float)), "The angle must be either a float or int." + + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + return img.rotate(angle, resample, expand, center) + + +def to_grayscale(img, num_output_channels=1): + """Convert image to grayscale version of image. + + Args: + img (PIL Image): Image to be converted to grayscale. + + Returns: + PIL Image: Grayscale version of the image. + if num_output_channels = 1 : returned image is single channel + if num_output_channels = 3 : returned image is 3 channel with r = g = b + if num_output_channels = 4 : returned image is 4 channel with r = g = b = a + """ + if not _is_pil_image(img): + raise TypeError('img should be PIL Image. Got {}'.format(type(img))) + + if num_output_channels == 1: + img = img.convert('L') + elif num_output_channels == 3: + img = img.convert('L') + np_img = np.array(img, dtype=np.uint8) + np_img = np.dstack([np_img, np_img, np_img]) + img = Image.fromarray(np_img, 'RGB') + elif num_output_channels == 4: + img = img.convert('L') + np_img = np.array(img, dtype=np.uint8) + np_img = np.dstack([np_img, np_img, np_img, np_img]) + img = Image.fromarray(np_img, 'RGBA') + else: + raise ValueError('num_output_channels should be either 1, 3 or 4') + + return img diff --git a/maxfw/utils/image_utils.py b/maxfw/utils/image_utils.py new file mode 100644 index 0000000..28dda5a --- /dev/null +++ b/maxfw/utils/image_utils.py @@ -0,0 +1,240 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# +from __future__ import division +import sys +from PIL import Image +import collections + +from . import image_functions as F + +if sys.version_info < (3, 3): + Sequence = collections.Sequence + Iterable = collections.Iterable +else: + Sequence = collections.abc.Sequence + Iterable = collections.abc.Iterable + + +class ImageProcessor(object): + """Composes several transforms together. + + Args: + transforms (list of ``Transform`` objects): sequence of transforms to compose. + + Example: + >>> pipeline = ImageProcessor([ + >>> Rotate(150), + >>> Resize([100,100]) + >>> ]) + >>> pipeline.apply_transforms(img) + """ + + def __init__(self, transforms=[]): + assert isinstance(transforms, Sequence) + self.transforms = transforms + + def apply_transforms(self, img): + """ + Sequentially apply the list of transformations to the input image. + + args: + img: an image in bytes format, as a Pillow image object, or a numpy ndarray + + output: + The transformed image. + Depending on the transformation the output is either a Pillow Image object or a numpy ndarray. + """ + # verify whether the Normalize or Standardize transformations are positioned at the end + encoding = [(isinstance(t, Normalize) or isinstance(t, Standardize)) for t in self.transforms] + assert sum(encoding[:-1]) == 0, \ + 'A Standardize or Normalize transformation must be positioned at the end of the pipeline.' + + # apply the transformations + for t in self.transforms: + img = t(img) + return img + + +class ToPILImage(object): + """Convert a byte stream or an ndarray to PIL Image. + + Converts a byte stream or a numpy ndarray of shape + H x W x C to a PIL Image while preserving the value range. + + Args: + mode (`PIL.Image mode`_): color space and pixel depth of input data (optional). + If ``mode`` is ``None`` (default) there are some assumptions made about the input data: + - If the input has 4 channels, the ``mode`` is assumed to be ``RGBA``. + - If the input has 3 channels, the ``mode`` is assumed to be ``RGB``. + - If the input has 2 channels, the ``mode`` is assumed to be ``LA``. + - If the input has 1 channel, the ``mode`` is determined by the data type (i.e ``int``, ``float``, + ``short``). + + .. _PIL.Image mode: https://pillow.readthedocs.io/en/latest/handbook/concepts.html#concept-modes + """ + def __init__(self, target_mode, mode=None): + self.mode = mode + self.target_mode = target_mode + + def __call__(self, pic): + """ + Args: + pic (bytestream or numpy.ndarray): Image to be converted to PIL Image. + + Returns: + PIL Image: Image converted to PIL Image. + + """ + return F.to_pil_image(pic, self.target_mode, self.mode) + + +class PILtoarray(object): + """ + onvert a PIL Image object to a numpy ndarray. + """ + + def __call__(self, pic): + """ + Args: + pic (PIL Image): Image to be converted to a numpy ndarray. + + Returns: + numpy ndarray + + """ + return F.pil_to_array(pic) + + +class Normalize(object): + """ + Normalize the image to a range between [0, 1]. + """ + + def __call__(self, img): + """ + Args: + img (PIL image or numpy.ndarray): Image to be normalized. + + Returns: + numpy.ndarray: Normalized image. + """ + return F.normalize(img) + + +class Standardize(object): + """ + Standardize the image (mean-centering and STD of 1). + + Args: + mean (optional): a single number or an n-dimensional sequence with n equal to the number of image channels + std (optional): a single number or an n-dimensional sequence with n equal to the number of image channels + Returns: + numpy.ndarray: standardized image + + If `mean` or `std` are not provided, the channel-wise values will be calculated for the input image. + """ + def __init__(self, mean=None, std=None): + self.mean = mean + self.std = std + + def __call__(self, img): + """ + Args: + img (PIL image or numpy.ndarray): Image to be standardized. + + Returns: + numpy.ndarray: Standardized image. + """ + return F.standardize(img, self.mean, self.std) + + +class Resize(object): + """Resize the input PIL Image to the given size. + + Args: + size (sequence or int): Desired output size. If size is a sequence like + (h, w), output size will be matched to this. If size is an int, + smaller edge of the image will be matched to this number. + i.e, if height > width, then image will be rescaled to + (size * height / width, size) + interpolation (int, optional): Desired interpolation. Default is + ``PIL.Image.BILINEAR`` + """ + + def __init__(self, size, interpolation=Image.BILINEAR): + assert isinstance(size, int) or (isinstance(size, Sequence) and len(size) == 2) + self.size = size + self.interpolation = interpolation + + def __call__(self, img): + """ + Args: + img (PIL Image): Image to be scaled. + + Returns: + PIL Image: Rescaled image. + """ + return F.resize(img, self.size, self.interpolation) + + +class Rotate(object): + """ + Rotate the input PIL Image by a given angle (counter clockwise). + + Args: + angle (int or float): Counter clockwise angle to rotate the image by. + """ + + def __init__(self, angle): + self.angle = angle + + def __call__(self, img): + """ + Args: + img (PIL Image): Image to be rotated. + + Returns: + PIL Image: Rotated image. + """ + return F.rotate(img, self.angle) + + +class Grayscale(object): + """Convert image to grayscale. + + Args: + num_output_channels (int): (1, 3 or 4) number of channels desired for output image + + Returns: + PIL Image: Grayscale version of the input. + - If num_output_channels == 1 : returned image is single channel + - If num_output_channels == 3 : returned image is 3 channel with r == g == b + - If num_output_channels == 4 : returned image is 3 channel with r == g == b == a + + """ + + def __init__(self, num_output_channels=1): + self.num_output_channels = num_output_channels + + def __call__(self, img): + """ + Args: + img (PIL Image): Image to be converted to grayscale. + + Returns: + PIL Image: Randomly grayscaled image. + """ + return F.to_grayscale(img, num_output_channels=self.num_output_channels) diff --git a/setup.py b/setup.py index e60f51f..e92c627 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,18 @@ +# +# Copyright 2018-2019 IBM Corp. 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. +# from setuptools import setup with open('README.md') as f: @@ -12,10 +27,13 @@ author='CODAIT', author_email='djalova@us.ibm.com, nickp@za.ibm.com, brendan.dwyer@ibm.com', license='Apache', - packages=['maxfw', 'maxfw.core', 'maxfw.model'], + packages=['maxfw', 'maxfw.core', 'maxfw.model', 'maxfw.utils'], zip_safe=True, install_requires=[ 'flask-restplus==0.11.0', 'flask-cors', + 'Pillow', ], + test_suite='nose.collector', + tests_require=['nose'] )