From 5a0f4d4b7c82065452f8591ea25815c3fa43e82f Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 14 Sep 2022 09:10:54 +0200 Subject: [PATCH 1/5] rename features.SegmentationMask -> features.Mask --- test/prototype_common_utils.py | 6 +- test/test_prototype_transforms.py | 30 ++++---- test/test_prototype_transforms_functional.py | 32 ++++----- test/test_prototype_transforms_utils.py | 72 +++++++++---------- torchvision/prototype/features/__init__.py | 2 +- .../prototype/features/_segmentation_mask.py | 46 ++++++------ torchvision/prototype/transforms/_augment.py | 10 +-- .../prototype/transforms/_auto_augment.py | 2 +- torchvision/prototype/transforms/_geometry.py | 14 ++-- torchvision/prototype/transforms/_misc.py | 2 +- 10 files changed, 107 insertions(+), 109 deletions(-) diff --git a/test/prototype_common_utils.py b/test/prototype_common_utils.py index 420754bb74e..bddbb03deb3 100644 --- a/test/prototype_common_utils.py +++ b/test/prototype_common_utils.py @@ -184,7 +184,7 @@ def make_detection_mask(size=None, *, num_objects=None, extra_dims=(), dtype=tor num_objects = num_objects if num_objects is not None else int(torch.randint(1, 11, ())) shape = (*extra_dims, num_objects, *size) data = make_tensor(shape, low=0, high=2, dtype=dtype) - return features.SegmentationMask(data) + return features.Mask(data) def make_detection_masks( @@ -207,7 +207,7 @@ def make_segmentation_mask(size=None, *, num_categories=None, extra_dims=(), dty num_categories = num_categories if num_categories is not None else int(torch.randint(1, 11, ())) shape = (*extra_dims, *size) data = make_tensor(shape, low=0, high=num_categories, dtype=dtype) - return features.SegmentationMask(data) + return features.Mask(data) def make_segmentation_masks( @@ -224,7 +224,7 @@ def make_segmentation_masks( yield make_segmentation_mask(size=sizes[0], num_categories=num_categories_, dtype=dtype, extra_dims=extra_dims_) -def make_detection_and_segmentation_masks( +def make_masks( sizes=((16, 16), (7, 33), (31, 9)), dtypes=(torch.uint8,), extra_dims=((), (0,), (4,), (2, 3), (5, 0), (0, 5)), diff --git a/test/test_prototype_transforms.py b/test/test_prototype_transforms.py index 64db07caa56..9dcfc84475d 100644 --- a/test/test_prototype_transforms.py +++ b/test/test_prototype_transforms.py @@ -10,11 +10,11 @@ from prototype_common_utils import ( make_bounding_box, make_bounding_boxes, - make_detection_and_segmentation_masks, make_detection_mask, make_image, make_images, make_label, + make_masks, make_one_hot_labels, make_segmentation_mask, ) @@ -64,7 +64,7 @@ def parametrize_from_transforms(*transforms): make_one_hot_labels, make_vanilla_tensor_images, make_pil_images, - make_detection_and_segmentation_masks, + make_masks, ]: inputs = list(creation_fn()) try: @@ -241,7 +241,7 @@ def test_convert_color_space_unsupported_types(self): color_space=features.ColorSpace.RGB, old_color_space=features.ColorSpace.GRAY ) - for inpt in [make_bounding_box(format="XYXY"), make_detection_and_segmentation_masks()]: + for inpt in [make_bounding_box(format="XYXY"), make_masks()]: output = transform(inpt) assert output is inpt @@ -282,9 +282,9 @@ def test_features_segmentation_mask(self, p): input, expected = self.input_expected_image_tensor(p) transform = transforms.RandomHorizontalFlip(p=p) - actual = transform(features.SegmentationMask(input)) + actual = transform(features.Mask(input)) - assert_equal(features.SegmentationMask(expected), actual) + assert_equal(features.Mask(expected), actual) def test_features_bounding_box(self, p): input = features.BoundingBox([0, 0, 5, 5], format=features.BoundingBoxFormat.XYXY, image_size=(10, 10)) @@ -335,9 +335,9 @@ def test_features_segmentation_mask(self, p): input, expected = self.input_expected_image_tensor(p) transform = transforms.RandomVerticalFlip(p=p) - actual = transform(features.SegmentationMask(input)) + actual = transform(features.Mask(input)) - assert_equal(features.SegmentationMask(expected), actual) + assert_equal(features.Mask(expected), actual) def test_features_bounding_box(self, p): input = features.BoundingBox([0, 0, 5, 5], format=features.BoundingBoxFormat.XYXY, image_size=(10, 10)) @@ -1253,7 +1253,7 @@ def test__transform(self, mocker): torch.testing.assert_close(output_ohe_label, ohe_label[is_within_crop_area]) output_masks = output[4] - assert isinstance(output_masks, features.SegmentationMask) + assert isinstance(output_masks, features.Mask) assert len(output_masks) == expected_within_targets @@ -1372,10 +1372,10 @@ def test__extract_image_targets_assertion(self, mocker): # labels, bboxes, masks mocker.MagicMock(spec=features.Label), mocker.MagicMock(spec=features.BoundingBox), - mocker.MagicMock(spec=features.SegmentationMask), + mocker.MagicMock(spec=features.Mask), # labels, bboxes, masks mocker.MagicMock(spec=features.BoundingBox), - mocker.MagicMock(spec=features.SegmentationMask), + mocker.MagicMock(spec=features.Mask), ] with pytest.raises(TypeError, match="requires input sample to contain equal sized list of Images"): @@ -1393,11 +1393,11 @@ def test__extract_image_targets(self, image_type, label_type, mocker): # labels, bboxes, masks mocker.MagicMock(spec=label_type), mocker.MagicMock(spec=features.BoundingBox), - mocker.MagicMock(spec=features.SegmentationMask), + mocker.MagicMock(spec=features.Mask), # labels, bboxes, masks mocker.MagicMock(spec=label_type), mocker.MagicMock(spec=features.BoundingBox), - mocker.MagicMock(spec=features.SegmentationMask), + mocker.MagicMock(spec=features.Mask), ] images, targets = transform._extract_image_targets(flat_sample) @@ -1413,7 +1413,7 @@ def test__extract_image_targets(self, image_type, label_type, mocker): for target in targets: for key, type_ in [ ("boxes", features.BoundingBox), - ("masks", features.SegmentationMask), + ("masks", features.Mask), ("labels", label_type), ]: assert key in target @@ -1436,7 +1436,7 @@ def test__copy_paste(self, label_type): "boxes": features.BoundingBox( torch.tensor([[2.0, 3.0, 8.0, 9.0], [20.0, 20.0, 30.0, 30.0]]), format="XYXY", image_size=(32, 32) ), - "masks": features.SegmentationMask(masks), + "masks": features.Mask(masks), "labels": label_type(labels), } @@ -1451,7 +1451,7 @@ def test__copy_paste(self, label_type): "boxes": features.BoundingBox( torch.tensor([[12.0, 13.0, 19.0, 18.0], [1.0, 15.0, 8.0, 19.0]]), format="XYXY", image_size=(32, 32) ), - "masks": features.SegmentationMask(paste_masks), + "masks": features.Mask(paste_masks), "labels": label_type(paste_labels), } diff --git a/test/test_prototype_transforms_functional.py b/test/test_prototype_transforms_functional.py index 3f9a0c2bd6e..bf11b7c2d5f 100644 --- a/test/test_prototype_transforms_functional.py +++ b/test/test_prototype_transforms_functional.py @@ -11,10 +11,10 @@ from prototype_common_utils import ( ArgsKwargs, make_bounding_boxes, - make_detection_and_segmentation_masks, make_detection_masks, make_image, make_images, + make_masks, ) from torch import jit from torchvision.prototype import features @@ -62,7 +62,7 @@ def horizontal_flip_bounding_box(): @register_kernel_info_from_sample_inputs_fn def horizontal_flip_segmentation_mask(): - for mask in make_detection_and_segmentation_masks(): + for mask in make_masks(): yield ArgsKwargs(mask) @@ -80,7 +80,7 @@ def vertical_flip_bounding_box(): @register_kernel_info_from_sample_inputs_fn def vertical_flip_segmentation_mask(): - for mask in make_detection_and_segmentation_masks(): + for mask in make_masks(): yield ArgsKwargs(mask) @@ -125,7 +125,7 @@ def resize_bounding_box(): @register_kernel_info_from_sample_inputs_fn def resize_segmentation_mask(): for mask, max_size in itertools.product( - make_detection_and_segmentation_masks(), + make_masks(), [None, 34], # max_size ): height, width = mask.shape[-2:] @@ -180,7 +180,7 @@ def affine_bounding_box(): @register_kernel_info_from_sample_inputs_fn def affine_segmentation_mask(): for mask, angle, translate, scale, shear in itertools.product( - make_detection_and_segmentation_masks(), + make_masks(), [-87, 15, 90], # angle [5, -5], # translate [0.77, 1.27], # scale @@ -233,7 +233,7 @@ def rotate_bounding_box(): @register_kernel_info_from_sample_inputs_fn def rotate_segmentation_mask(): for mask, angle, expand, center in itertools.product( - make_detection_and_segmentation_masks(), + make_masks(), [-87, 15, 90], # angle [True, False], # expand [None, [12, 23]], # center @@ -275,9 +275,7 @@ def crop_bounding_box(): @register_kernel_info_from_sample_inputs_fn def crop_segmentation_mask(): - for mask, top, left, height, width in itertools.product( - make_detection_and_segmentation_masks(), [-8, 0, 9], [-8, 0, 9], [12, 20], [12, 20] - ): + for mask, top, left, height, width in itertools.product(make_masks(), [-8, 0, 9], [-8, 0, 9], [12, 20], [12, 20]): yield ArgsKwargs( mask, top=top, @@ -314,7 +312,7 @@ def resized_crop_bounding_box(): @register_kernel_info_from_sample_inputs_fn def resized_crop_segmentation_mask(): for mask, top, left, height, width, size in itertools.product( - make_detection_and_segmentation_masks(), [-8, 0, 9], [-8, 0, 9], [12, 20], [12, 20], [(32, 32), (16, 18)] + make_masks(), [-8, 0, 9], [-8, 0, 9], [12, 20], [12, 20], [(32, 32), (16, 18)] ): yield ArgsKwargs(mask, top=top, left=left, height=height, width=width, size=size) @@ -333,7 +331,7 @@ def pad_image_tensor(): @register_kernel_info_from_sample_inputs_fn def pad_segmentation_mask(): for mask, padding, padding_mode in itertools.product( - make_detection_and_segmentation_masks(), + make_masks(), [[1], [1, 1], [1, 1, 2, 2]], # padding ["constant", "symmetric", "edge", "reflect"], # padding mode, ): @@ -381,7 +379,7 @@ def perspective_bounding_box(): @register_kernel_info_from_sample_inputs_fn def perspective_segmentation_mask(): for mask, perspective_coeffs in itertools.product( - make_detection_and_segmentation_masks(extra_dims=((), (4,))), + make_masks(extra_dims=((), (4,))), [ [1.2405, 0.1772, -6.9113, 0.0463, 1.251, -5.235, 0.00013, 0.0018], [0.7366, -0.11724, 1.45775, -0.15012, 0.73406, 2.6019, -0.0072, -0.0063], @@ -418,7 +416,7 @@ def elastic_bounding_box(): @register_kernel_info_from_sample_inputs_fn def elastic_segmentation_mask(): - for mask in make_detection_and_segmentation_masks(extra_dims=((), (4,))): + for mask in make_masks(extra_dims=((), (4,))): h, w = mask.shape[-2:] displacement = torch.rand(1, h, w, 2) yield ArgsKwargs( @@ -447,7 +445,7 @@ def center_crop_bounding_box(): @register_kernel_info_from_sample_inputs_fn def center_crop_segmentation_mask(): for mask, output_size in itertools.product( - make_detection_and_segmentation_masks(sizes=((16, 16), (7, 33), (31, 9))), + make_masks(sizes=((16, 16), (7, 33), (31, 9))), [[4, 3], [42, 70], [4]], # crop sizes < image sizes, crop_sizes > image sizes, single crop size ): yield ArgsKwargs(mask, output_size) @@ -1147,7 +1145,7 @@ def _compute_expected_mask(mask, top_, left_, height_, width_): return expected - for mask in make_detection_and_segmentation_masks(): + for mask in make_masks(): if mask.device != torch.device(device): mask = mask.to(device) output_mask = F.crop_segmentation_mask(mask, top, left, height, width) @@ -1367,7 +1365,7 @@ def _compute_expected_mask(mask, padding_, padding_mode_): return output - for mask in make_detection_and_segmentation_masks(): + for mask in make_masks(): out_mask = F.pad_segmentation_mask(mask, padding, padding_mode=padding_mode) expected_mask = _compute_expected_mask(mask, padding, padding_mode) @@ -1681,7 +1679,7 @@ def test_correctness_elastic_image_or_mask_tensor(device, fn, make_samples): sample = features.Image(sample) kwargs = {"interpolation": F.InterpolationMode.NEAREST} else: - sample = features.SegmentationMask(sample) + sample = features.Mask(sample) kwargs = {} # Create a displacement grid using sin diff --git a/test/test_prototype_transforms_utils.py b/test/test_prototype_transforms_utils.py index 386b47d7a1c..9a8ed67dde2 100644 --- a/test/test_prototype_transforms_utils.py +++ b/test/test_prototype_transforms_utils.py @@ -12,30 +12,30 @@ IMAGE = make_image(color_space=features.ColorSpace.RGB) BOUNDING_BOX = make_bounding_box(format=features.BoundingBoxFormat.XYXY, image_size=IMAGE.image_size) -SEGMENTATION_MASK = make_detection_mask(size=IMAGE.image_size) +MASK = make_detection_mask(size=IMAGE.image_size) @pytest.mark.parametrize( ("sample", "types", "expected"), [ - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.Image,), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.BoundingBox,), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.SegmentationMask,), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.Image, features.BoundingBox), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.Image, features.SegmentationMask), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.BoundingBox, features.SegmentationMask), True), - ((SEGMENTATION_MASK,), (features.Image, features.BoundingBox), False), - ((BOUNDING_BOX,), (features.Image, features.SegmentationMask), False), - ((IMAGE,), (features.BoundingBox, features.SegmentationMask), False), + ((IMAGE, BOUNDING_BOX, MASK), (features.Image,), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox,), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.Mask,), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.BoundingBox), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.Mask), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox, features.Mask), True), + ((MASK,), (features.Image, features.BoundingBox), False), + ((BOUNDING_BOX,), (features.Image, features.Mask), False), + ((IMAGE,), (features.BoundingBox, features.Mask), False), ( - (IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), - (features.Image, features.BoundingBox, features.SegmentationMask), + (IMAGE, BOUNDING_BOX, MASK), + (features.Image, features.BoundingBox, features.Mask), True, ), - ((), (features.Image, features.BoundingBox, features.SegmentationMask), False), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (lambda obj: isinstance(obj, features.Image),), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (lambda _: False,), False), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (lambda _: True,), True), + ((), (features.Image, features.BoundingBox, features.Mask), False), + ((IMAGE, BOUNDING_BOX, MASK), (lambda obj: isinstance(obj, features.Image),), True), + ((IMAGE, BOUNDING_BOX, MASK), (lambda _: False,), False), + ((IMAGE, BOUNDING_BOX, MASK), (lambda _: True,), True), ((IMAGE,), (features.Image, PIL.Image.Image, features.is_simple_tensor), True), ((torch.Tensor(IMAGE),), (features.Image, PIL.Image.Image, features.is_simple_tensor), True), ((to_image_pil(IMAGE),), (features.Image, PIL.Image.Image, features.is_simple_tensor), True), @@ -48,35 +48,35 @@ def test_has_any(sample, types, expected): @pytest.mark.parametrize( ("sample", "types", "expected"), [ - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.Image,), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.BoundingBox,), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.SegmentationMask,), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.Image, features.BoundingBox), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.Image, features.SegmentationMask), True), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (features.BoundingBox, features.SegmentationMask), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.Image,), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox,), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.Mask,), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.BoundingBox), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.Image, features.Mask), True), + ((IMAGE, BOUNDING_BOX, MASK), (features.BoundingBox, features.Mask), True), ( - (IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), - (features.Image, features.BoundingBox, features.SegmentationMask), + (IMAGE, BOUNDING_BOX, MASK), + (features.Image, features.BoundingBox, features.Mask), True, ), - ((BOUNDING_BOX, SEGMENTATION_MASK), (features.Image, features.BoundingBox), False), - ((BOUNDING_BOX, SEGMENTATION_MASK), (features.Image, features.SegmentationMask), False), - ((IMAGE, SEGMENTATION_MASK), (features.BoundingBox, features.SegmentationMask), False), + ((BOUNDING_BOX, MASK), (features.Image, features.BoundingBox), False), + ((BOUNDING_BOX, MASK), (features.Image, features.Mask), False), + ((IMAGE, MASK), (features.BoundingBox, features.Mask), False), ( - (IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), - (features.Image, features.BoundingBox, features.SegmentationMask), + (IMAGE, BOUNDING_BOX, MASK), + (features.Image, features.BoundingBox, features.Mask), True, ), - ((BOUNDING_BOX, SEGMENTATION_MASK), (features.Image, features.BoundingBox, features.SegmentationMask), False), - ((IMAGE, SEGMENTATION_MASK), (features.Image, features.BoundingBox, features.SegmentationMask), False), - ((IMAGE, BOUNDING_BOX), (features.Image, features.BoundingBox, features.SegmentationMask), False), + ((BOUNDING_BOX, MASK), (features.Image, features.BoundingBox, features.Mask), False), + ((IMAGE, MASK), (features.Image, features.BoundingBox, features.Mask), False), + ((IMAGE, BOUNDING_BOX), (features.Image, features.BoundingBox, features.Mask), False), ( - (IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), - (lambda obj: isinstance(obj, (features.Image, features.BoundingBox, features.SegmentationMask)),), + (IMAGE, BOUNDING_BOX, MASK), + (lambda obj: isinstance(obj, (features.Image, features.BoundingBox, features.Mask)),), True, ), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (lambda _: False,), False), - ((IMAGE, BOUNDING_BOX, SEGMENTATION_MASK), (lambda _: True,), True), + ((IMAGE, BOUNDING_BOX, MASK), (lambda _: False,), False), + ((IMAGE, BOUNDING_BOX, MASK), (lambda _: True,), True), ], ) def test_has_all(sample, types, expected): diff --git a/torchvision/prototype/features/__init__.py b/torchvision/prototype/features/__init__.py index 51b2e6bedcd..85364742c7e 100644 --- a/torchvision/prototype/features/__init__.py +++ b/torchvision/prototype/features/__init__.py @@ -3,4 +3,4 @@ from ._feature import _Feature, is_simple_tensor from ._image import ColorSpace, Image from ._label import Label, OneHotLabel -from ._segmentation_mask import SegmentationMask +from ._segmentation_mask import Mask diff --git a/torchvision/prototype/features/_segmentation_mask.py b/torchvision/prototype/features/_segmentation_mask.py index 57d00ea6aa2..776ba94d5cd 100644 --- a/torchvision/prototype/features/_segmentation_mask.py +++ b/torchvision/prototype/features/_segmentation_mask.py @@ -8,14 +8,14 @@ from ._feature import _Feature -class SegmentationMask(_Feature): - def horizontal_flip(self) -> SegmentationMask: +class Mask(_Feature): + def horizontal_flip(self) -> Mask: output = self._F.horizontal_flip_segmentation_mask(self) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) - def vertical_flip(self) -> SegmentationMask: + def vertical_flip(self) -> Mask: output = self._F.vertical_flip_segmentation_mask(self) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) def resize( # type: ignore[override] self, @@ -23,17 +23,17 @@ def resize( # type: ignore[override] interpolation: InterpolationMode = InterpolationMode.NEAREST, max_size: Optional[int] = None, antialias: bool = False, - ) -> SegmentationMask: + ) -> Mask: output = self._F.resize_segmentation_mask(self, size, max_size=max_size) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) - def crop(self, top: int, left: int, height: int, width: int) -> SegmentationMask: + def crop(self, top: int, left: int, height: int, width: int) -> Mask: output = self._F.crop_segmentation_mask(self, top, left, height, width) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) - def center_crop(self, output_size: List[int]) -> SegmentationMask: + def center_crop(self, output_size: List[int]) -> Mask: output = self._F.center_crop_segmentation_mask(self, output_size=output_size) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) def resized_crop( self, @@ -44,22 +44,22 @@ def resized_crop( size: List[int], interpolation: InterpolationMode = InterpolationMode.NEAREST, antialias: bool = False, - ) -> SegmentationMask: + ) -> Mask: output = self._F.resized_crop_segmentation_mask(self, top, left, height, width, size=size) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) def pad( self, padding: Union[int, Sequence[int]], fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, padding_mode: str = "constant", - ) -> SegmentationMask: + ) -> Mask: # This cast does Sequence[int] -> List[int] and is required to make mypy happy if not isinstance(padding, int): padding = list(padding) output = self._F.pad_segmentation_mask(self, padding, padding_mode=padding_mode) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) def rotate( self, @@ -68,9 +68,9 @@ def rotate( expand: bool = False, fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, center: Optional[List[float]] = None, - ) -> SegmentationMask: + ) -> Mask: output = self._F.rotate_segmentation_mask(self, angle, expand=expand, center=center) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) def affine( self, @@ -81,7 +81,7 @@ def affine( interpolation: InterpolationMode = InterpolationMode.NEAREST, fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, center: Optional[List[float]] = None, - ) -> SegmentationMask: + ) -> Mask: output = self._F.affine_segmentation_mask( self, angle, @@ -90,22 +90,22 @@ def affine( shear=shear, center=center, ) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) def perspective( self, perspective_coeffs: List[float], interpolation: InterpolationMode = InterpolationMode.NEAREST, fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, - ) -> SegmentationMask: + ) -> Mask: output = self._F.perspective_segmentation_mask(self, perspective_coeffs) - return SegmentationMask.new_like(self, output) + return Mask.new_like(self, output) def elastic( self, displacement: torch.Tensor, interpolation: InterpolationMode = InterpolationMode.NEAREST, fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, - ) -> SegmentationMask: + ) -> Mask: output = self._F.elastic_segmentation_mask(self, displacement) - return SegmentationMask.new_like(self, output, dtype=output.dtype) + return Mask.new_like(self, output, dtype=output.dtype) diff --git a/torchvision/prototype/transforms/_augment.py b/torchvision/prototype/transforms/_augment.py index d552f626fa3..8e652240db5 100644 --- a/torchvision/prototype/transforms/_augment.py +++ b/torchvision/prototype/transforms/_augment.py @@ -108,7 +108,7 @@ def __init__(self, alpha: float, p: float = 0.5) -> None: def forward(self, *inputs: Any) -> Any: if not (has_any(inputs, features.Image, features.is_simple_tensor) and has_any(inputs, features.OneHotLabel)): raise TypeError(f"{type(self).__name__}() is only defined for tensor images and one-hot labels.") - if has_any(inputs, features.BoundingBox, features.SegmentationMask, features.Label): + if has_any(inputs, features.BoundingBox, features.Mask, features.Label): raise TypeError( f"{type(self).__name__}() does not support bounding boxes, segmentation masks and plain labels." ) @@ -280,7 +280,7 @@ def _copy_paste( def _extract_image_targets(self, flat_sample: List[Any]) -> Tuple[List[Any], List[Dict[str, Any]]]: # fetch all images, bboxes, masks and labels from unstructured input - # with List[image], List[BoundingBox], List[SegmentationMask], List[Label] + # with List[image], List[BoundingBox], List[Mask], List[Label] images, bboxes, masks, labels = [], [], [], [] for obj in flat_sample: if isinstance(obj, features.Image) or features.is_simple_tensor(obj): @@ -289,7 +289,7 @@ def _extract_image_targets(self, flat_sample: List[Any]) -> Tuple[List[Any], Lis images.append(F.to_image_tensor(obj)) elif isinstance(obj, features.BoundingBox): bboxes.append(obj) - elif isinstance(obj, features.SegmentationMask): + elif isinstance(obj, features.Mask): masks.append(obj) elif isinstance(obj, (features.Label, features.OneHotLabel)): labels.append(obj) @@ -323,8 +323,8 @@ def _insert_outputs( elif isinstance(obj, features.BoundingBox): flat_sample[i] = features.BoundingBox.new_like(obj, output_targets[c1]["boxes"]) c1 += 1 - elif isinstance(obj, features.SegmentationMask): - flat_sample[i] = features.SegmentationMask.new_like(obj, output_targets[c2]["masks"]) + elif isinstance(obj, features.Mask): + flat_sample[i] = features.Mask.new_like(obj, output_targets[c2]["masks"]) c2 += 1 elif isinstance(obj, (features.Label, features.OneHotLabel)): flat_sample[i] = obj.new_like(obj, output_targets[c3]["labels"]) # type: ignore[arg-type] diff --git a/torchvision/prototype/transforms/_auto_augment.py b/torchvision/prototype/transforms/_auto_augment.py index 5db521fbb98..611aac05a2e 100644 --- a/torchvision/prototype/transforms/_auto_augment.py +++ b/torchvision/prototype/transforms/_auto_augment.py @@ -38,7 +38,7 @@ def _get_random_item(self, dct: Dict[K, V]) -> Tuple[K, V]: def _extract_image( self, sample: Any, - unsupported_types: Tuple[Type, ...] = (features.BoundingBox, features.SegmentationMask), + unsupported_types: Tuple[Type, ...] = (features.BoundingBox, features.Mask), ) -> Tuple[int, Union[PIL.Image.Image, torch.Tensor, features.Image]]: sample_flat, _ = tree_flatten(sample) images = [] diff --git a/torchvision/prototype/transforms/_geometry.py b/torchvision/prototype/transforms/_geometry.py index cdecf440516..2b7b44119ca 100644 --- a/torchvision/prototype/transforms/_geometry.py +++ b/torchvision/prototype/transforms/_geometry.py @@ -170,8 +170,8 @@ def _transform(self, inpt: DType, params: Dict[str, Any]) -> Tuple[DType, DType, return F.five_crop(inpt, self.size) def forward(self, *inputs: Any) -> Any: - if has_any(inputs, features.BoundingBox, features.SegmentationMask): - raise TypeError(f"BoundingBox'es and SegmentationMask's are not supported by {type(self).__name__}()") + if has_any(inputs, features.BoundingBox, features.Mask): + raise TypeError(f"BoundingBox'es and Mask's are not supported by {type(self).__name__}()") return super().forward(*inputs) @@ -191,8 +191,8 @@ def _transform(self, inpt: DType, params: Dict[str, Any]) -> List[DType]: return F.ten_crop(inpt, self.size, vertical_flip=self.vertical_flip) def forward(self, *inputs: Any) -> Any: - if has_any(inputs, features.BoundingBox, features.SegmentationMask): - raise TypeError(f"BoundingBox'es and SegmentationMask's are not supported by {type(self).__name__}()") + if has_any(inputs, features.BoundingBox, features.Mask): + raise TypeError(f"BoundingBox'es and Mask's are not supported by {type(self).__name__}()") return super().forward(*inputs) @@ -690,10 +690,10 @@ def _transform(self, inpt: Any, params: Dict[str, Any]) -> Any: bboxes = output[is_within_crop_area] bboxes = F.clamp_bounding_box(bboxes, output.format, output.image_size) output = features.BoundingBox.new_like(output, bboxes) - elif isinstance(output, features.SegmentationMask) and output.shape[-3] > 1: + elif isinstance(output, features.Mask) and output.shape[-3] > 1: # apply is_within_crop_area if mask is one-hot encoded masks = output[is_within_crop_area] - output = features.SegmentationMask.new_like(output, masks) + output = features.Mask.new_like(output, masks) return output @@ -842,7 +842,7 @@ def _transform(self, inpt: Any, params: Dict[str, Any]) -> Any: ) if params["is_valid"] is not None: - if isinstance(inpt, (features.Label, features.OneHotLabel, features.SegmentationMask)): + if isinstance(inpt, (features.Label, features.OneHotLabel, features.Mask)): inpt = inpt.new_like(inpt, inpt[params["is_valid"]]) # type: ignore[arg-type] elif isinstance(inpt, features.BoundingBox): inpt = features.BoundingBox.new_like( diff --git a/torchvision/prototype/transforms/_misc.py b/torchvision/prototype/transforms/_misc.py index d797e41ec25..661737d66f1 100644 --- a/torchvision/prototype/transforms/_misc.py +++ b/torchvision/prototype/transforms/_misc.py @@ -150,7 +150,7 @@ def extra_repr(self) -> str: class RemoveSmallBoundingBoxes(Transform): - _transformed_types = (features.BoundingBox, features.SegmentationMask, features.Label, features.OneHotLabel) + _transformed_types = (features.BoundingBox, features.Mask, features.Label, features.OneHotLabel) def __init__(self, min_size: float = 1.0) -> None: super().__init__() From 267f00f27b0b5545ffe0b8d3c7acd49579e92c80 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 14 Sep 2022 09:20:06 +0200 Subject: [PATCH 2/5] rename kernels *_segmentation_mask -> *_mask and cleanup input name --- test/test_prototype_transforms_functional.py | 66 ++++++++-------- .../prototype/features/_segmentation_mask.py | 20 ++--- .../transforms/functional/__init__.py | 22 +++--- .../transforms/functional/_geometry.py | 78 +++++++++---------- 4 files changed, 91 insertions(+), 95 deletions(-) diff --git a/test/test_prototype_transforms_functional.py b/test/test_prototype_transforms_functional.py index bf11b7c2d5f..6cf32c90146 100644 --- a/test/test_prototype_transforms_functional.py +++ b/test/test_prototype_transforms_functional.py @@ -61,7 +61,7 @@ def horizontal_flip_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def horizontal_flip_segmentation_mask(): +def horizontal_flip_mask(): for mask in make_masks(): yield ArgsKwargs(mask) @@ -79,7 +79,7 @@ def vertical_flip_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def vertical_flip_segmentation_mask(): +def vertical_flip_mask(): for mask in make_masks(): yield ArgsKwargs(mask) @@ -123,7 +123,7 @@ def resize_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def resize_segmentation_mask(): +def resize_mask(): for mask, max_size in itertools.product( make_masks(), [None, 34], # max_size @@ -178,7 +178,7 @@ def affine_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def affine_segmentation_mask(): +def affine_mask(): for mask, angle, translate, scale, shear in itertools.product( make_masks(), [-87, 15, 90], # angle @@ -231,7 +231,7 @@ def rotate_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def rotate_segmentation_mask(): +def rotate_mask(): for mask, angle, expand, center in itertools.product( make_masks(), [-87, 15, 90], # angle @@ -274,7 +274,7 @@ def crop_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def crop_segmentation_mask(): +def crop_mask(): for mask, top, left, height, width in itertools.product(make_masks(), [-8, 0, 9], [-8, 0, 9], [12, 20], [12, 20]): yield ArgsKwargs( mask, @@ -310,7 +310,7 @@ def resized_crop_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def resized_crop_segmentation_mask(): +def resized_crop_mask(): for mask, top, left, height, width, size in itertools.product( make_masks(), [-8, 0, 9], [-8, 0, 9], [12, 20], [12, 20], [(32, 32), (16, 18)] ): @@ -329,7 +329,7 @@ def pad_image_tensor(): @register_kernel_info_from_sample_inputs_fn -def pad_segmentation_mask(): +def pad_mask(): for mask, padding, padding_mode in itertools.product( make_masks(), [[1], [1, 1], [1, 1, 2, 2]], # padding @@ -377,7 +377,7 @@ def perspective_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def perspective_segmentation_mask(): +def perspective_mask(): for mask, perspective_coeffs in itertools.product( make_masks(extra_dims=((), (4,))), [ @@ -415,7 +415,7 @@ def elastic_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def elastic_segmentation_mask(): +def elastic_mask(): for mask in make_masks(extra_dims=((), (4,))): h, w = mask.shape[-2:] displacement = torch.rand(1, h, w, 2) @@ -443,7 +443,7 @@ def center_crop_bounding_box(): @register_kernel_info_from_sample_inputs_fn -def center_crop_segmentation_mask(): +def center_crop_mask(): for mask, output_size in itertools.product( make_masks(sizes=((16, 16), (7, 33), (31, 9))), [[4, 3], [42, 70], [4]], # crop sizes < image sizes, crop_sizes > image sizes, single crop size @@ -758,7 +758,7 @@ def test_correctness_affine_bounding_box_on_fixed_input(device): @pytest.mark.parametrize("scale", [0.89, 1.12]) @pytest.mark.parametrize("shear", [4]) @pytest.mark.parametrize("center", [None, (12, 14)]) -def test_correctness_affine_segmentation_mask(angle, translate, scale, shear, center): +def test_correctness_affine_mask(angle, translate, scale, shear, center): def _compute_expected_mask(mask, angle_, translate_, scale_, shear_, center_): assert mask.ndim == 3 affine_matrix = _compute_affine_matrix(angle_, translate_, scale_, shear_, center_) @@ -778,7 +778,7 @@ def _compute_expected_mask(mask, angle_, translate_, scale_, shear_, center_): # FIXME: `_compute_expected_mask` currently only works for "detection" masks. Extend it for "segmentation" masks. for mask in make_detection_masks(extra_dims=((), (4,))): - output_mask = F.affine_segmentation_mask( + output_mask = F.affine_mask( mask, angle=angle, translate=(translate, translate), @@ -822,7 +822,7 @@ def test_correctness_affine_segmentation_mask_on_fixed_input(device): expected_mask = torch.nn.functional.interpolate(expected_mask[None, :].float(), size=(64, 64), mode="nearest") expected_mask = expected_mask[0, :, 16 : 64 - 16, 16 : 64 - 16].long() - out_mask = F.affine_segmentation_mask(mask, 90, [0.0, 0.0], 64.0 / 32.0, [0.0, 0.0]) + out_mask = F.affine_mask(mask, 90, [0.0, 0.0], 64.0 / 32.0, [0.0, 0.0]) torch.testing.assert_close(out_mask, expected_mask) @@ -974,7 +974,7 @@ def test_correctness_rotate_bounding_box_on_fixed_input(device, expand): @pytest.mark.parametrize("angle", range(-89, 90, 37)) @pytest.mark.parametrize("expand, center", [(True, None), (False, None), (False, (12, 14))]) -def test_correctness_rotate_segmentation_mask(angle, expand, center): +def test_correctness_rotate_mask(angle, expand, center): def _compute_expected_mask(mask, angle_, expand_, center_): assert mask.ndim == 3 c, *image_size = mask.shape @@ -1019,7 +1019,7 @@ def _compute_expected_mask(mask, angle_, expand_, center_): # FIXME: `_compute_expected_mask` currently only works for "detection" masks. Extend it for "segmentation" masks. for mask in make_detection_masks(extra_dims=((), (4,))): - output_mask = F.rotate_segmentation_mask( + output_mask = F.rotate_mask( mask, angle=angle, expand=expand, @@ -1058,7 +1058,7 @@ def test_correctness_rotate_segmentation_mask_on_fixed_input(device): # Rotate 90 degrees expected_mask = torch.rot90(mask, k=1, dims=(-2, -1)) - out_mask = F.rotate_segmentation_mask(mask, 90, expand=False) + out_mask = F.rotate_mask(mask, 90, expand=False) torch.testing.assert_close(out_mask, expected_mask) @@ -1121,7 +1121,7 @@ def test_correctness_crop_bounding_box(device, format, top, left, height, width, [-8, -6, 70, 8], ], ) -def test_correctness_crop_segmentation_mask(device, top, left, height, width): +def test_correctness_crop_mask(device, top, left, height, width): def _compute_expected_mask(mask, top_, left_, height_, width_): h, w = mask.shape[-2], mask.shape[-1] if top_ >= 0 and left_ >= 0 and top_ + height_ < h and left_ + width_ < w: @@ -1148,7 +1148,7 @@ def _compute_expected_mask(mask, top_, left_, height_, width_): for mask in make_masks(): if mask.device != torch.device(device): mask = mask.to(device) - output_mask = F.crop_segmentation_mask(mask, top, left, height, width) + output_mask = F.crop_mask(mask, top, left, height, width) expected_mask = _compute_expected_mask(mask, top, left, height, width) torch.testing.assert_close(output_mask, expected_mask) @@ -1158,7 +1158,7 @@ def test_correctness_horizontal_flip_segmentation_mask_on_fixed_input(device): mask = torch.zeros((3, 3, 3), dtype=torch.long, device=device) mask[:, :, 0] = 1 - out_mask = F.horizontal_flip_segmentation_mask(mask) + out_mask = F.horizontal_flip_mask(mask) expected_mask = torch.zeros((3, 3, 3), dtype=torch.long, device=device) expected_mask[:, :, -1] = 1 @@ -1170,7 +1170,7 @@ def test_correctness_vertical_flip_segmentation_mask_on_fixed_input(device): mask = torch.zeros((3, 3, 3), dtype=torch.long, device=device) mask[:, 0, :] = 1 - out_mask = F.vertical_flip_segmentation_mask(mask) + out_mask = F.vertical_flip_mask(mask) expected_mask = torch.zeros((3, 3, 3), dtype=torch.long, device=device) expected_mask[:, -1, :] = 1 @@ -1231,7 +1231,7 @@ def _compute_expected_bbox(bbox, top_, left_, height_, width_, size_): [5, 5, 35, 45, (32, 34)], ], ) -def test_correctness_resized_crop_segmentation_mask(device, top, left, height, width, size): +def test_correctness_resized_crop_mask(device, top, left, height, width, size): def _compute_expected_mask(mask, top_, left_, height_, width_, size_): output = mask.clone() output = output[:, top_ : top_ + height_, left_ : left_ + width_] @@ -1244,7 +1244,7 @@ def _compute_expected_mask(mask, top_, left_, height_, width_, size_): in_mask[0, 5:15, 12:23] = 2 expected_mask = _compute_expected_mask(in_mask, top, left, height, width, size) - output_mask = F.resized_crop_segmentation_mask(in_mask, top, left, height, width, size) + output_mask = F.resized_crop_mask(in_mask, top, left, height, width, size) torch.testing.assert_close(output_mask, expected_mask) @@ -1308,7 +1308,7 @@ def _compute_expected_bbox(bbox, padding_): def test_correctness_pad_segmentation_mask_on_fixed_input(device): mask = torch.ones((1, 3, 3), dtype=torch.long, device=device) - out_mask = F.pad_segmentation_mask(mask, padding=[1, 1, 1, 1]) + out_mask = F.pad_mask(mask, padding=[1, 1, 1, 1]) expected_mask = torch.zeros((1, 5, 5), dtype=torch.long, device=device) expected_mask[:, 1:-1, 1:-1] = 1 @@ -1317,7 +1317,7 @@ def test_correctness_pad_segmentation_mask_on_fixed_input(device): @pytest.mark.parametrize("padding", [[1, 2, 3, 4], [1], 1, [1, 2]]) @pytest.mark.parametrize("padding_mode", ["constant", "edge", "reflect", "symmetric"]) -def test_correctness_pad_segmentation_mask(padding, padding_mode): +def test_correctness_pad_mask(padding, padding_mode): def _compute_expected_mask(mask, padding_, padding_mode_): h, w = mask.shape[-2], mask.shape[-1] pad_left, pad_up, pad_right, pad_down = _parse_padding(padding_) @@ -1366,7 +1366,7 @@ def _compute_expected_mask(mask, padding_, padding_mode_): return output for mask in make_masks(): - out_mask = F.pad_segmentation_mask(mask, padding, padding_mode=padding_mode) + out_mask = F.pad_mask(mask, padding, padding_mode=padding_mode) expected_mask = _compute_expected_mask(mask, padding, padding_mode) torch.testing.assert_close(out_mask, expected_mask) @@ -1471,7 +1471,7 @@ def _compute_expected_bbox(bbox, pcoeffs_): [[[3, 2], [32, 3], [30, 24], [2, 25]], [[5, 5], [30, 3], [33, 19], [4, 25]]], ], ) -def test_correctness_perspective_segmentation_mask(device, startpoints, endpoints): +def test_correctness_perspective_mask(device, startpoints, endpoints): def _compute_expected_mask(mask, pcoeffs_): assert mask.ndim == 3 m1 = np.array([[pcoeffs_[0], pcoeffs_[1], pcoeffs_[2]], [pcoeffs_[3], pcoeffs_[4], pcoeffs_[5]]]) @@ -1498,7 +1498,7 @@ def _compute_expected_mask(mask, pcoeffs_): for mask in make_detection_masks(extra_dims=((), (4,))): mask = mask.to(device) - output_mask = F.perspective_segmentation_mask( + output_mask = F.perspective_mask( mask, perspective_coeffs=pcoeffs, ) @@ -1577,8 +1577,8 @@ def _compute_expected_bbox(bbox, output_size_): @pytest.mark.parametrize("device", cpu_and_gpu()) @pytest.mark.parametrize("output_size", [[4, 2], [4], [7, 6]]) -def test_correctness_center_crop_segmentation_mask(device, output_size): - def _compute_expected_segmentation_mask(mask, output_size): +def test_correctness_center_crop_mask(device, output_size): + def _compute_expected_mask(mask, output_size): crop_height, crop_width = output_size if len(output_size) > 1 else [output_size[0], output_size[0]] _, image_height, image_width = mask.shape @@ -1592,9 +1592,9 @@ def _compute_expected_segmentation_mask(mask, output_size): return mask[:, top : top + crop_height, left : left + crop_width] mask = torch.randint(0, 2, size=(1, 6, 6), dtype=torch.long, device=device) - actual = F.center_crop_segmentation_mask(mask, output_size) + actual = F.center_crop_mask(mask, output_size) - expected = _compute_expected_segmentation_mask(mask, output_size) + expected = _compute_expected_mask(mask, output_size) torch.testing.assert_close(expected, actual) @@ -1661,7 +1661,7 @@ def test_correctness_gaussian_blur_image_tensor(device, image_size, dt, ksize, s [ (F.elastic_image_tensor, make_images), # FIXME: This test currently only works for "detection" masks. Extend it for "segmentation" masks. - (F.elastic_segmentation_mask, make_detection_masks), + (F.elastic_mask, make_detection_masks), ], ) def test_correctness_elastic_image_or_mask_tensor(device, fn, make_samples): diff --git a/torchvision/prototype/features/_segmentation_mask.py b/torchvision/prototype/features/_segmentation_mask.py index 776ba94d5cd..9727e5a5588 100644 --- a/torchvision/prototype/features/_segmentation_mask.py +++ b/torchvision/prototype/features/_segmentation_mask.py @@ -10,11 +10,11 @@ class Mask(_Feature): def horizontal_flip(self) -> Mask: - output = self._F.horizontal_flip_segmentation_mask(self) + output = self._F.horizontal_flip_mask(self) return Mask.new_like(self, output) def vertical_flip(self) -> Mask: - output = self._F.vertical_flip_segmentation_mask(self) + output = self._F.vertical_flip_mask(self) return Mask.new_like(self, output) def resize( # type: ignore[override] @@ -24,15 +24,15 @@ def resize( # type: ignore[override] max_size: Optional[int] = None, antialias: bool = False, ) -> Mask: - output = self._F.resize_segmentation_mask(self, size, max_size=max_size) + output = self._F.resize_mask(self, size, max_size=max_size) return Mask.new_like(self, output) def crop(self, top: int, left: int, height: int, width: int) -> Mask: - output = self._F.crop_segmentation_mask(self, top, left, height, width) + output = self._F.crop_mask(self, top, left, height, width) return Mask.new_like(self, output) def center_crop(self, output_size: List[int]) -> Mask: - output = self._F.center_crop_segmentation_mask(self, output_size=output_size) + output = self._F.center_crop_mask(self, output_size=output_size) return Mask.new_like(self, output) def resized_crop( @@ -45,7 +45,7 @@ def resized_crop( interpolation: InterpolationMode = InterpolationMode.NEAREST, antialias: bool = False, ) -> Mask: - output = self._F.resized_crop_segmentation_mask(self, top, left, height, width, size=size) + output = self._F.resized_crop_mask(self, top, left, height, width, size=size) return Mask.new_like(self, output) def pad( @@ -58,7 +58,7 @@ def pad( if not isinstance(padding, int): padding = list(padding) - output = self._F.pad_segmentation_mask(self, padding, padding_mode=padding_mode) + output = self._F.pad_mask(self, padding, padding_mode=padding_mode) return Mask.new_like(self, output) def rotate( @@ -69,7 +69,7 @@ def rotate( fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, center: Optional[List[float]] = None, ) -> Mask: - output = self._F.rotate_segmentation_mask(self, angle, expand=expand, center=center) + output = self._F.rotate_mask(self, angle, expand=expand, center=center) return Mask.new_like(self, output) def affine( @@ -98,7 +98,7 @@ def perspective( interpolation: InterpolationMode = InterpolationMode.NEAREST, fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, ) -> Mask: - output = self._F.perspective_segmentation_mask(self, perspective_coeffs) + output = self._F.perspective_mask(self, perspective_coeffs) return Mask.new_like(self, output) def elastic( @@ -107,5 +107,5 @@ def elastic( interpolation: InterpolationMode = InterpolationMode.NEAREST, fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, ) -> Mask: - output = self._F.elastic_segmentation_mask(self, displacement) + output = self._F.elastic_mask(self, displacement) return Mask.new_like(self, output, dtype=output.dtype) diff --git a/torchvision/prototype/transforms/functional/__init__.py b/torchvision/prototype/transforms/functional/__init__.py index 9a7a16e7c94..e3344470973 100644 --- a/torchvision/prototype/transforms/functional/__init__.py +++ b/torchvision/prototype/transforms/functional/__init__.py @@ -53,22 +53,22 @@ affine_bounding_box, affine_image_pil, affine_image_tensor, - affine_segmentation_mask, + affine_mask, center_crop, center_crop_bounding_box, center_crop_image_pil, center_crop_image_tensor, - center_crop_segmentation_mask, + center_crop_mask, crop, crop_bounding_box, crop_image_pil, crop_image_tensor, - crop_segmentation_mask, + crop_mask, elastic, elastic_bounding_box, elastic_image_pil, elastic_image_tensor, - elastic_segmentation_mask, + elastic_mask, elastic_transform, five_crop, five_crop_image_pil, @@ -78,32 +78,32 @@ horizontal_flip_bounding_box, horizontal_flip_image_pil, horizontal_flip_image_tensor, - horizontal_flip_segmentation_mask, + horizontal_flip_mask, pad, pad_bounding_box, pad_image_pil, pad_image_tensor, - pad_segmentation_mask, + pad_mask, perspective, perspective_bounding_box, perspective_image_pil, perspective_image_tensor, - perspective_segmentation_mask, + perspective_mask, resize, resize_bounding_box, resize_image_pil, resize_image_tensor, - resize_segmentation_mask, + resize_mask, resized_crop, resized_crop_bounding_box, resized_crop_image_pil, resized_crop_image_tensor, - resized_crop_segmentation_mask, + resized_crop_mask, rotate, rotate_bounding_box, rotate_image_pil, rotate_image_tensor, - rotate_segmentation_mask, + rotate_mask, ten_crop, ten_crop_image_pil, ten_crop_image_tensor, @@ -111,7 +111,7 @@ vertical_flip_bounding_box, vertical_flip_image_pil, vertical_flip_image_tensor, - vertical_flip_segmentation_mask, + vertical_flip_mask, vflip, ) from ._misc import gaussian_blur, gaussian_blur_image_pil, gaussian_blur_image_tensor, normalize, normalize_image_tensor diff --git a/torchvision/prototype/transforms/functional/_geometry.py b/torchvision/prototype/transforms/functional/_geometry.py index 021eb8ef6ab..b79236ed03d 100644 --- a/torchvision/prototype/transforms/functional/_geometry.py +++ b/torchvision/prototype/transforms/functional/_geometry.py @@ -28,8 +28,8 @@ horizontal_flip_image_pil = _FP.hflip -def horizontal_flip_segmentation_mask(segmentation_mask: torch.Tensor) -> torch.Tensor: - return horizontal_flip_image_tensor(segmentation_mask) +def horizontal_flip_mask(mask: torch.Tensor) -> torch.Tensor: + return horizontal_flip_image_tensor(mask) def horizontal_flip_bounding_box( @@ -61,8 +61,8 @@ def horizontal_flip(inpt: DType) -> DType: vertical_flip_image_pil = _FP.vflip -def vertical_flip_segmentation_mask(segmentation_mask: torch.Tensor) -> torch.Tensor: - return vertical_flip_image_tensor(segmentation_mask) +def vertical_flip_mask(mask: torch.Tensor) -> torch.Tensor: + return vertical_flip_image_tensor(mask) def vertical_flip_bounding_box( @@ -132,10 +132,8 @@ def resize_image_pil( return _FP.resize(img, size, interpolation=pil_modes_mapping[interpolation]) -def resize_segmentation_mask( - segmentation_mask: torch.Tensor, size: List[int], max_size: Optional[int] = None -) -> torch.Tensor: - return resize_image_tensor(segmentation_mask, size=size, interpolation=InterpolationMode.NEAREST, max_size=max_size) +def resize_mask(mask: torch.Tensor, size: List[int], max_size: Optional[int] = None) -> torch.Tensor: + return resize_image_tensor(mask, size=size, interpolation=InterpolationMode.NEAREST, max_size=max_size) def resize_bounding_box( @@ -366,22 +364,22 @@ def affine_bounding_box( ).view(original_shape) -def affine_segmentation_mask( - segmentation_mask: torch.Tensor, +def affine_mask( + mask: torch.Tensor, angle: float, translate: List[float], scale: float, shear: List[float], center: Optional[List[float]] = None, ) -> torch.Tensor: - if segmentation_mask.ndim < 3: - segmentation_mask = segmentation_mask.unsqueeze(0) + if mask.ndim < 3: + mask = mask.unsqueeze(0) needs_squeeze = True else: needs_squeeze = False output = affine_image_tensor( - segmentation_mask, + mask, angle=angle, translate=translate, scale=scale, @@ -532,20 +530,20 @@ def rotate_bounding_box( ).view(original_shape) -def rotate_segmentation_mask( - segmentation_mask: torch.Tensor, +def rotate_mask( + mask: torch.Tensor, angle: float, expand: bool = False, center: Optional[List[float]] = None, ) -> torch.Tensor: - if segmentation_mask.ndim < 3: - segmentation_mask = segmentation_mask.unsqueeze(0) + if mask.ndim < 3: + mask = mask.unsqueeze(0) needs_squeeze = True else: needs_squeeze = False output = rotate_image_tensor( - segmentation_mask, + mask, angle=angle, expand=expand, interpolation=InterpolationMode.NEAREST, @@ -626,16 +624,14 @@ def _pad_with_vector_fill( return output -def pad_segmentation_mask( - segmentation_mask: torch.Tensor, padding: Union[int, List[int]], padding_mode: str = "constant" -) -> torch.Tensor: - if segmentation_mask.ndim < 3: - segmentation_mask = segmentation_mask.unsqueeze(0) +def pad_mask(mask: torch.Tensor, padding: Union[int, List[int]], padding_mode: str = "constant") -> torch.Tensor: + if mask.ndim < 3: + mask = mask.unsqueeze(0) needs_squeeze = True else: needs_squeeze = False - output = pad_image_tensor(img=segmentation_mask, padding=padding, fill=0, padding_mode=padding_mode) + output = pad_image_tensor(img=mask, padding=padding, fill=0, padding_mode=padding_mode) if needs_squeeze: output = output.squeeze(0) @@ -710,8 +706,8 @@ def crop_bounding_box( ) -def crop_segmentation_mask(img: torch.Tensor, top: int, left: int, height: int, width: int) -> torch.Tensor: - return crop_image_tensor(img, top, left, height, width) +def crop_mask(mask: torch.Tensor, top: int, left: int, height: int, width: int) -> torch.Tensor: + return crop_image_tensor(mask, top, left, height, width) def crop(inpt: DType, top: int, left: int, height: int, width: int) -> DType: @@ -826,15 +822,15 @@ def perspective_bounding_box( ).view(original_shape) -def perspective_segmentation_mask(segmentation_mask: torch.Tensor, perspective_coeffs: List[float]) -> torch.Tensor: - if segmentation_mask.ndim < 3: - segmentation_mask = segmentation_mask.unsqueeze(0) +def perspective_mask(mask: torch.Tensor, perspective_coeffs: List[float]) -> torch.Tensor: + if mask.ndim < 3: + mask = mask.unsqueeze(0) needs_squeeze = True else: needs_squeeze = False output = perspective_image_tensor( - segmentation_mask, perspective_coeffs=perspective_coeffs, interpolation=InterpolationMode.NEAREST + mask, perspective_coeffs=perspective_coeffs, interpolation=InterpolationMode.NEAREST ) if needs_squeeze: @@ -924,14 +920,14 @@ def elastic_bounding_box( ).view(original_shape) -def elastic_segmentation_mask(segmentation_mask: torch.Tensor, displacement: torch.Tensor) -> torch.Tensor: - if segmentation_mask.ndim < 3: - segmentation_mask = segmentation_mask.unsqueeze(0) +def elastic_mask(mask: torch.Tensor, displacement: torch.Tensor) -> torch.Tensor: + if mask.ndim < 3: + mask = mask.unsqueeze(0) needs_squeeze = True else: needs_squeeze = False - output = elastic_image_tensor(segmentation_mask, displacement=displacement, interpolation=InterpolationMode.NEAREST) + output = elastic_image_tensor(mask, displacement=displacement, interpolation=InterpolationMode.NEAREST) if needs_squeeze: output = output.squeeze(0) @@ -1027,14 +1023,14 @@ def center_crop_bounding_box( return crop_bounding_box(bounding_box, format, top=crop_top, left=crop_left) -def center_crop_segmentation_mask(segmentation_mask: torch.Tensor, output_size: List[int]) -> torch.Tensor: - if segmentation_mask.ndim < 3: - segmentation_mask = segmentation_mask.unsqueeze(0) +def center_crop_mask(mask: torch.Tensor, output_size: List[int]) -> torch.Tensor: + if mask.ndim < 3: + mask = mask.unsqueeze(0) needs_squeeze = True else: needs_squeeze = False - output = center_crop_image_tensor(img=segmentation_mask, output_size=output_size) + output = center_crop_image_tensor(img=mask, output_size=output_size) if needs_squeeze: output = output.squeeze(0) @@ -1091,7 +1087,7 @@ def resized_crop_bounding_box( return resize_bounding_box(bounding_box, size, (height, width)) -def resized_crop_segmentation_mask( +def resized_crop_mask( mask: torch.Tensor, top: int, left: int, @@ -1099,8 +1095,8 @@ def resized_crop_segmentation_mask( width: int, size: List[int], ) -> torch.Tensor: - mask = crop_segmentation_mask(mask, top, left, height, width) - return resize_segmentation_mask(mask, size) + mask = crop_mask(mask, top, left, height, width) + return resize_mask(mask, size) def resized_crop( From a806a223dfa465f7390316e9c9b12635424ca8f4 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 14 Sep 2022 09:27:14 +0200 Subject: [PATCH 3/5] cleanup --- test/test_prototype_transforms.py | 10 +++++----- test/test_prototype_transforms_functional.py | 6 ++---- torchvision/prototype/features/_segmentation_mask.py | 2 +- torchvision/prototype/transforms/_augment.py | 6 ++---- torchvision/prototype/transforms/_geometry.py | 2 +- 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/test/test_prototype_transforms.py b/test/test_prototype_transforms.py index 9dcfc84475d..878a0aac812 100644 --- a/test/test_prototype_transforms.py +++ b/test/test_prototype_transforms.py @@ -278,7 +278,7 @@ def test_features_image(self, p): assert_equal(features.Image(expected), actual) - def test_features_segmentation_mask(self, p): + def test_features_mask(self, p): input, expected = self.input_expected_image_tensor(p) transform = transforms.RandomHorizontalFlip(p=p) @@ -331,7 +331,7 @@ def test_features_image(self, p): assert_equal(features.Image(expected), actual) - def test_features_segmentation_mask(self, p): + def test_features_mask(self, p): input, expected = self.input_expected_image_tensor(p) transform = transforms.RandomVerticalFlip(p=p) @@ -1586,7 +1586,7 @@ def test__transform_culling(self, mocker): bounding_boxes = make_bounding_box( format=features.BoundingBoxFormat.XYXY, image_size=image_size, extra_dims=(batch_size,) ) - segmentation_masks = make_detection_mask(size=image_size, extra_dims=(batch_size,)) + masks = make_detection_mask(size=image_size, extra_dims=(batch_size,)) labels = make_label(size=(batch_size,)) transform = transforms.FixedSizeCrop((-1, -1)) @@ -1596,13 +1596,13 @@ def test__transform_culling(self, mocker): output = transform( dict( bounding_boxes=bounding_boxes, - segmentation_masks=segmentation_masks, + masks=masks, labels=labels, ) ) assert_equal(output["bounding_boxes"], bounding_boxes[is_valid]) - assert_equal(output["segmentation_masks"], segmentation_masks[is_valid]) + assert_equal(output["masks"], masks[is_valid]) assert_equal(output["labels"], labels[is_valid]) def test__transform_bounding_box_clamping(self, mocker): diff --git a/test/test_prototype_transforms_functional.py b/test/test_prototype_transforms_functional.py index 6cf32c90146..5cecbed3d76 100644 --- a/test/test_prototype_transforms_functional.py +++ b/test/test_prototype_transforms_functional.py @@ -526,7 +526,7 @@ def erase_image_tensor(): for name, kernel in F.__dict__.items() if not name.startswith("_") and callable(kernel) - and any(feature_type in name for feature_type in {"image", "segmentation_mask", "bounding_box", "label"}) + and any(feature_type in name for feature_type in {"image", "mask", "bounding_box", "label"}) and "pil" not in name and name not in { @@ -551,9 +551,7 @@ def test_scriptable(kernel): for name, func in F.__dict__.items() if not name.startswith("_") and callable(func) - and all( - feature_type not in name for feature_type in {"image", "segmentation_mask", "bounding_box", "label", "pil"} - ) + and all(feature_type not in name for feature_type in {"image", "mask", "bounding_box", "label", "pil"}) and name not in { "to_image_tensor", diff --git a/torchvision/prototype/features/_segmentation_mask.py b/torchvision/prototype/features/_segmentation_mask.py index 9727e5a5588..b78eeb1cf12 100644 --- a/torchvision/prototype/features/_segmentation_mask.py +++ b/torchvision/prototype/features/_segmentation_mask.py @@ -82,7 +82,7 @@ def affine( fill: Optional[Union[int, float, Sequence[int], Sequence[float]]] = None, center: Optional[List[float]] = None, ) -> Mask: - output = self._F.affine_segmentation_mask( + output = self._F.affine_mask( self, angle, translate=translate, diff --git a/torchvision/prototype/transforms/_augment.py b/torchvision/prototype/transforms/_augment.py index 8e652240db5..cf3ef39d476 100644 --- a/torchvision/prototype/transforms/_augment.py +++ b/torchvision/prototype/transforms/_augment.py @@ -109,9 +109,7 @@ def forward(self, *inputs: Any) -> Any: if not (has_any(inputs, features.Image, features.is_simple_tensor) and has_any(inputs, features.OneHotLabel)): raise TypeError(f"{type(self).__name__}() is only defined for tensor images and one-hot labels.") if has_any(inputs, features.BoundingBox, features.Mask, features.Label): - raise TypeError( - f"{type(self).__name__}() does not support bounding boxes, segmentation masks and plain labels." - ) + raise TypeError(f"{type(self).__name__}() does not support bounding boxes, masks and plain labels.") return super().forward(*inputs) def _mixup_onehotlabel(self, inpt: features.OneHotLabel, lam: float) -> features.OneHotLabel: @@ -297,7 +295,7 @@ def _extract_image_targets(self, flat_sample: List[Any]) -> Tuple[List[Any], Lis if not (len(images) == len(bboxes) == len(masks) == len(labels)): raise TypeError( f"{type(self).__name__}() requires input sample to contain equal sized list of Images, " - "BoundingBoxes, Segmentation Masks and Labels or OneHotLabels." + "BoundingBoxes, Masks and Labels or OneHotLabels." ) targets = [] diff --git a/torchvision/prototype/transforms/_geometry.py b/torchvision/prototype/transforms/_geometry.py index 2b7b44119ca..70910f72723 100644 --- a/torchvision/prototype/transforms/_geometry.py +++ b/torchvision/prototype/transforms/_geometry.py @@ -705,7 +705,7 @@ def forward(self, *inputs: Any) -> Any: ): raise TypeError( f"{type(self).__name__}() requires input sample to contain Images or PIL Images, " - "BoundingBoxes and Labels or OneHotLabels. Sample can also contain Segmentation Masks." + "BoundingBoxes and Labels or OneHotLabels. Sample can also contain Masks." ) return super().forward(*inputs) From de0ca59f4e4194e93d78a78bc22f4471e61c6811 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 14 Sep 2022 09:28:18 +0200 Subject: [PATCH 4/5] rename module _segmentation_mask.py -> _mask.py --- torchvision/prototype/features/__init__.py | 2 +- .../prototype/features/{_segmentation_mask.py => _mask.py} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename torchvision/prototype/features/{_segmentation_mask.py => _mask.py} (100%) diff --git a/torchvision/prototype/features/__init__.py b/torchvision/prototype/features/__init__.py index 85364742c7e..5b2e6658acd 100644 --- a/torchvision/prototype/features/__init__.py +++ b/torchvision/prototype/features/__init__.py @@ -3,4 +3,4 @@ from ._feature import _Feature, is_simple_tensor from ._image import ColorSpace, Image from ._label import Label, OneHotLabel -from ._segmentation_mask import Mask +from ._mask import Mask diff --git a/torchvision/prototype/features/_segmentation_mask.py b/torchvision/prototype/features/_mask.py similarity index 100% rename from torchvision/prototype/features/_segmentation_mask.py rename to torchvision/prototype/features/_mask.py From 46f7aa0db907aaa354f1115c8e063b6d253aded9 Mon Sep 17 00:00:00 2001 From: Philip Meier Date: Wed, 14 Sep 2022 09:32:54 +0200 Subject: [PATCH 5/5] fix test --- test/test_prototype_transforms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_prototype_transforms.py b/test/test_prototype_transforms.py index 878a0aac812..83cbed0f902 100644 --- a/test/test_prototype_transforms.py +++ b/test/test_prototype_transforms.py @@ -132,7 +132,7 @@ def test_mixup_cutmix(self, transform, input): transform(input_copy) # Check if we raise an error if sample contains bbox or mask or label - err_msg = "does not support bounding boxes, segmentation masks and plain labels" + err_msg = "does not support bounding boxes, masks and plain labels" input_copy = dict(input) for unsup_data in [ make_label(),