From 06c7f0a43e13555ebc77e36d53149e7572f2b384 Mon Sep 17 00:00:00 2001 From: vfdev Date: Tue, 30 Jun 2020 18:02:16 +0200 Subject: [PATCH] Improved docs and tests for (#2371) - RandomCrop: crop with padding using all commonly supported modes --- test/test_transforms_tensor.py | 56 +++++++++++---------- torchvision/transforms/functional.py | 2 +- torchvision/transforms/functional_tensor.py | 3 +- torchvision/transforms/transforms.py | 3 +- 4 files changed, 35 insertions(+), 29 deletions(-) diff --git a/test/test_transforms_tensor.py b/test/test_transforms_tensor.py index 1d2d92bb3ae..6a8d9930754 100644 --- a/test/test_transforms_tensor.py +++ b/test/test_transforms_tensor.py @@ -26,24 +26,29 @@ def _test_functional_geom_op(self, func, fn_kwargs): transformed_pil_img = getattr(F, func)(pil_img, **fn_kwargs) self.compareTensorToPIL(transformed_tensor, transformed_pil_img) - def _test_geom_op(self, func, method, fn_kwargs=None, meth_kwargs=None): - if fn_kwargs is None: - fn_kwargs = {} + def _test_class_geom_op(self, method, meth_kwargs=None): if meth_kwargs is None: meth_kwargs = {} + tensor, pil_img = self._create_data(height=10, width=10) - transformed_tensor = getattr(F, func)(tensor, **fn_kwargs) - transformed_pil_img = getattr(F, func)(pil_img, **fn_kwargs) + # test for class interface + f = getattr(T, method)(**meth_kwargs) + scripted_fn = torch.jit.script(f) + + # set seed to reproduce the same transformation for tensor and PIL image + torch.manual_seed(12) + transformed_tensor = f(tensor) + torch.manual_seed(12) + transformed_pil_img = f(pil_img) self.compareTensorToPIL(transformed_tensor, transformed_pil_img) - scripted_fn = torch.jit.script(getattr(F, func)) - transformed_tensor_script = scripted_fn(tensor, **fn_kwargs) + torch.manual_seed(12) + transformed_tensor_script = scripted_fn(tensor) self.assertTrue(transformed_tensor.equal(transformed_tensor_script)) - # test for class interface - f = getattr(T, method)(**meth_kwargs) - scripted_fn = torch.jit.script(f) - scripted_fn(tensor) + def _test_geom_op(self, func, method, fn_kwargs=None, meth_kwargs=None): + self._test_functional_geom_op(func, fn_kwargs) + self._test_class_geom_op(method, meth_kwargs) def test_random_horizontal_flip(self): self._test_geom_op('hflip', 'RandomHorizontalFlip') @@ -107,21 +112,20 @@ def test_crop(self): 'crop', 'RandomCrop', fn_kwargs=fn_kwargs, meth_kwargs=meth_kwargs ) - tensor = torch.randint(0, 255, (3, 10, 10), dtype=torch.uint8) - # Test torchscript of transforms.RandomCrop with size as int - f = T.RandomCrop(size=5) - scripted_fn = torch.jit.script(f) - scripted_fn(tensor) - - # Test torchscript of transforms.RandomCrop with size as [int, ] - f = T.RandomCrop(size=[5, ], padding=[2, ]) - scripted_fn = torch.jit.script(f) - scripted_fn(tensor) - - # Test torchscript of transforms.RandomCrop with size as list - f = T.RandomCrop(size=[6, 6]) - scripted_fn = torch.jit.script(f) - scripted_fn(tensor) + sizes = [5, [5, ], [6, 6]] + padding_configs = [ + {"padding_mode": "constant", "fill": 0}, + {"padding_mode": "constant", "fill": 10}, + {"padding_mode": "constant", "fill": 20}, + {"padding_mode": "edge"}, + {"padding_mode": "reflect"}, + ] + + for size in sizes: + for padding_config in padding_configs: + config = dict(padding_config) + config["size"] = size + self._test_class_geom_op("RandomCrop", config) def test_center_crop(self): fn_kwargs = {"output_size": (4, 5)} diff --git a/torchvision/transforms/functional.py b/torchvision/transforms/functional.py index cda26348552..81a601a8e20 100644 --- a/torchvision/transforms/functional.py +++ b/torchvision/transforms/functional.py @@ -371,7 +371,7 @@ def pad(img: Tensor, padding: List[int], fill: int = 0, padding_mode: str = "con length 3, it is used to fill R, G, B channels respectively. This value is only used when the padding_mode is constant. Only int value is supported for Tensors. padding_mode: Type of padding. Should be: constant, edge, reflect or symmetric. Default is constant. - Only "constant" is supported for Tensors as of now. + Mode symmetric is not yet supported for Tensor inputs. - constant: pads with a constant value, this value is specified with fill diff --git a/torchvision/transforms/functional_tensor.py b/torchvision/transforms/functional_tensor.py index c77e393569c..d4a8f340997 100644 --- a/torchvision/transforms/functional_tensor.py +++ b/torchvision/transforms/functional_tensor.py @@ -368,7 +368,8 @@ def pad(img: Tensor, padding: List[int], fill: int = 0, padding_mode: str = "con list of length 1: ``[padding, ]``. fill (int): Pixel fill value for constant fill. Default is 0. This value is only used when the padding_mode is constant - padding_mode (str): Type of padding. Only "constant" is supported for Tensors as of now. + padding_mode (str): Type of padding. Should be: constant, edge or reflect. Default is constant. + Mode symmetric is not yet supported for Tensor inputs. - constant: pads with a constant value, this value is specified with fill diff --git a/torchvision/transforms/transforms.py b/torchvision/transforms/transforms.py index 6ee266d5f79..a5214ed3174 100644 --- a/torchvision/transforms/transforms.py +++ b/torchvision/transforms/transforms.py @@ -305,7 +305,7 @@ class Pad(torch.nn.Module): length 3, it is used to fill R, G, B channels respectively. This value is only used when the padding_mode is constant padding_mode (str): Type of padding. Should be: constant, edge, reflect or symmetric. - Default is constant. Only "constant" is supported for Tensors as of now. + Default is constant. Mode symmetric is not yet supported for Tensor inputs. - constant: pads with a constant value, this value is specified with fill @@ -469,6 +469,7 @@ class RandomCrop(torch.nn.Module): length 3, it is used to fill R, G, B channels respectively. This value is only used when the padding_mode is constant padding_mode (str): Type of padding. Should be: constant, edge, reflect or symmetric. Default is constant. + Mode symmetric is not yet supported for Tensor inputs. - constant: pads with a constant value, this value is specified with fill