From 49a377160ed6c34ba0171bdd8335f0d98af6d8bd Mon Sep 17 00:00:00 2001 From: Mohammad Adil Date: Thu, 27 Feb 2020 17:01:58 -0800 Subject: [PATCH 1/5] Add Resize transform (spatial scaling). --- monai/transforms/transforms.py | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/monai/transforms/transforms.py b/monai/transforms/transforms.py index dc6f571106..37394961af 100644 --- a/monai/transforms/transforms.py +++ b/monai/transforms/transforms.py @@ -14,7 +14,11 @@ """ import numpy as np +<<<<<<< HEAD import torch +======= +from skimage.transform import resize +>>>>>>> Add Resize transform (spatial scaling). import monai from monai.data.utils import get_random_patch, get_valid_patch_size @@ -80,6 +84,45 @@ def __call__(self, img): return np.flip(img, self.axis) +class Resize: + """ + Resize the input image to given resolution. Uses skimage.transform.resize underneath. + For additional details, see https://scikit-image.org/docs/dev/api/skimage.transform.html#skimage.transform.resize. + + Args: + order (int): Order of spline interpolation. Default=1. + mode (str): Points outside boundaries are filled according to given mode. + Options are 'constant', 'edge', 'symmetric', 'reflect', 'wrap'. + cval (float): Used with mode 'constant', the value outside image boundaries. + clip (bool): Wheter to clip range of output values after interpolation. Default: True. + preserve_range (bool): Whether to keep original range of values. Default is True. + If False, input is converted according to conventions of img_as_float. See + https://scikit-image.org/docs/dev/user_guide/data_types.html. + anti_aliasing (bool): Whether to apply a gaussian filter to image before down-scaling. + Default is True. + anti_aliasing_sigma (float, tuple of floats): Standard deviation for gaussian filtering. + """ + + def __init__(self, order=1, mode='reflect', cval=0, + clip=True, preserve_range=True, + anti_aliasing=True, anti_aliasing_sigma=None): + assert isinstance(order, int), "order must be integer." + self.order = order + self.mode = mode + self.cval = cval + self.clip = clip + self.preserve_range = preserve_range + self.anti_aliasing = anti_aliasing + self.anti_aliasing_sigma = anti_aliasing_sigma + + def __call__(self, img, output_shape): + return resize(img, output_shape, + mode=self.mode, cval=self.cval, + clip=self.clip, preserve_range=self.preserve_range, + anti_aliasing=self.anti_aliasing, + anti_aliasing_sigma=self.anti_aliasing_sigma) + + @export class ToTensor: """ From aa76c799224690ae11b68f109db36c613a34cd73 Mon Sep 17 00:00:00 2001 From: Mohammad Adil Date: Thu, 27 Feb 2020 17:05:24 -0800 Subject: [PATCH 2/5] Adding tests. --- tests/test_spatial_transforms.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/test_spatial_transforms.py diff --git a/tests/test_spatial_transforms.py b/tests/test_spatial_transforms.py new file mode 100644 index 0000000000..95fa728e88 --- /dev/null +++ b/tests/test_spatial_transforms.py @@ -0,0 +1,16 @@ +# Copyright 2020 MONAI Consortium +# 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 unittest + +from parameterized import parameterized + +from monai.transforms import Resize \ No newline at end of file From aa8dfbf681cc5bbb34f8681e4b00ad5e15b5c30e Mon Sep 17 00:00:00 2001 From: Mohammad Adil Date: Mon, 2 Mar 2020 21:56:02 -0800 Subject: [PATCH 3/5] Add tests and fix errors. --- monai/transforms/transforms.py | 11 +++---- tests/test_resize.py | 52 ++++++++++++++++++++++++++++++++ tests/test_spatial_transforms.py | 16 ---------- 3 files changed, 57 insertions(+), 22 deletions(-) create mode 100644 tests/test_resize.py delete mode 100644 tests/test_spatial_transforms.py diff --git a/monai/transforms/transforms.py b/monai/transforms/transforms.py index 37394961af..50db0d612f 100644 --- a/monai/transforms/transforms.py +++ b/monai/transforms/transforms.py @@ -14,11 +14,8 @@ """ import numpy as np -<<<<<<< HEAD import torch -======= from skimage.transform import resize ->>>>>>> Add Resize transform (spatial scaling). import monai from monai.data.utils import get_random_patch, get_valid_patch_size @@ -84,6 +81,7 @@ def __call__(self, img): return np.flip(img, self.axis) +@export class Resize: """ Resize the input image to given resolution. Uses skimage.transform.resize underneath. @@ -103,10 +101,11 @@ class Resize: anti_aliasing_sigma (float, tuple of floats): Standard deviation for gaussian filtering. """ - def __init__(self, order=1, mode='reflect', cval=0, + def __init__(self, output_shape, order=1, mode='reflect', cval=0, clip=True, preserve_range=True, anti_aliasing=True, anti_aliasing_sigma=None): assert isinstance(order, int), "order must be integer." + self.output_shape = output_shape self.order = order self.mode = mode self.cval = cval @@ -115,8 +114,8 @@ def __init__(self, order=1, mode='reflect', cval=0, self.anti_aliasing = anti_aliasing self.anti_aliasing_sigma = anti_aliasing_sigma - def __call__(self, img, output_shape): - return resize(img, output_shape, + def __call__(self, img): + return resize(img, self.output_shape, mode=self.mode, cval=self.cval, clip=self.clip, preserve_range=self.preserve_range, anti_aliasing=self.anti_aliasing, diff --git a/tests/test_resize.py b/tests/test_resize.py new file mode 100644 index 0000000000..51f54e8c86 --- /dev/null +++ b/tests/test_resize.py @@ -0,0 +1,52 @@ +# Copyright 2020 MONAI Consortium +# 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 unittest + +import numpy as np +import skimage +from parameterized import parameterized + +from monai.transforms import Resize +from tests.utils import NumpyImageTestCase2D + + +class ResizeTest(NumpyImageTestCase2D): + + @parameterized.expand([ + ("invalid_order", "order", AssertionError) + ]) + def test_invalid_inputs(self, _, order, raises): + with self.assertRaises(raises): + resize = Resize(output_shape=(128, 128, 3), order=order) + resize(self.imt) + + @parameterized.expand([ + ((64, 64, 3), 1, 'reflect', 0, True, True, True, None), + ((32, 32, 3), 2, 'constant', 1, False, False, False, None) + ]) + def test_correct_results(self, output_shape, order, mode, + cval, clip, preserve_range, + anti_aliasing, anti_aliasing_sigma): + resize = Resize(output_shape, order, mode, cval, clip, + preserve_range, anti_aliasing, + anti_aliasing_sigma) + expected = skimage.transform.resize(self.imt, output_shape, + order=order, mode=mode, + cval=cval, clip=clip, + preserve_range=preserve_range, + anti_aliasing=anti_aliasing, + anti_aliasing_sigma=anti_aliasing_sigma) + self.assertTrue(np.allclose(resize(self.imt), expected)) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_spatial_transforms.py b/tests/test_spatial_transforms.py deleted file mode 100644 index 95fa728e88..0000000000 --- a/tests/test_spatial_transforms.py +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2020 MONAI Consortium -# 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 unittest - -from parameterized import parameterized - -from monai.transforms import Resize \ No newline at end of file From abbb743e7ea4701ba5a436aefe0ae038cbc43192 Mon Sep 17 00:00:00 2001 From: Mohammad Adil Date: Wed, 4 Mar 2020 20:03:12 -0800 Subject: [PATCH 4/5] Fix resize not using order. --- monai/transforms/transforms.py | 2 +- tests/test_resize.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/monai/transforms/transforms.py b/monai/transforms/transforms.py index 50db0d612f..408b291a58 100644 --- a/monai/transforms/transforms.py +++ b/monai/transforms/transforms.py @@ -115,7 +115,7 @@ def __init__(self, output_shape, order=1, mode='reflect', cval=0, self.anti_aliasing_sigma = anti_aliasing_sigma def __call__(self, img): - return resize(img, self.output_shape, + return resize(img, self.output_shape, order=self.order, mode=self.mode, cval=self.cval, clip=self.clip, preserve_range=self.preserve_range, anti_aliasing=self.anti_aliasing, diff --git a/tests/test_resize.py b/tests/test_resize.py index 51f54e8c86..7feaf9f634 100644 --- a/tests/test_resize.py +++ b/tests/test_resize.py @@ -30,8 +30,9 @@ def test_invalid_inputs(self, _, order, raises): resize(self.imt) @parameterized.expand([ - ((64, 64, 3), 1, 'reflect', 0, True, True, True, None), - ((32, 32, 3), 2, 'constant', 1, False, False, False, None) + ((1, 1, 64, 64), 1, 'reflect', 0, True, True, True, None), + ((1, 1, 32, 32), 2, 'constant', 3, False, False, False, None), + ((1, 1, 256, 256), 3, 'constant', 3, False, False, False, None), ]) def test_correct_results(self, output_shape, order, mode, cval, clip, preserve_range, From b6a3d6794cb04c75761798cfc598ca1033601a2b Mon Sep 17 00:00:00 2001 From: Wenqi Li Date: Thu, 5 Mar 2020 11:53:18 +0000 Subject: [PATCH 5/5] export the class --- monai/transforms/transforms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/monai/transforms/transforms.py b/monai/transforms/transforms.py index 604ad731f1..4447cdd282 100644 --- a/monai/transforms/transforms.py +++ b/monai/transforms/transforms.py @@ -123,6 +123,7 @@ def __call__(self, img): anti_aliasing_sigma=self.anti_aliasing_sigma) +@export class Rotate: """ Rotates an input image by given angle. Uses scipy.ndimage.rotate. For more details, see