Skip to content

Commit 541dbe2

Browse files
NicolasHugfacebook-github-bot
authored andcommitted
[fbsync] port affine tests (#7708)
Reviewed By: vmoens Differential Revision: D47186575 fbshipit-source-id: 93dcb9c8c60dc702870dfe6cc5c0d2a2a178a77c
1 parent 50e3255 commit 541dbe2

5 files changed

+453
-416
lines changed

test/test_transforms_v2.py

Lines changed: 0 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -668,130 +668,6 @@ def test_boundingbox_spatial_size(self, angle, expand):
668668
assert out_img.spatial_size == out_bbox.spatial_size
669669

670670

671-
class TestRandomAffine:
672-
def test_assertions(self):
673-
with pytest.raises(ValueError, match="is a single number, it must be positive"):
674-
transforms.RandomAffine(-0.7)
675-
676-
for d in [[-0.7], [-0.7, 0, 0.7]]:
677-
with pytest.raises(ValueError, match="degrees should be a sequence of length 2"):
678-
transforms.RandomAffine(d)
679-
680-
with pytest.raises(TypeError, match="Got inappropriate fill arg"):
681-
transforms.RandomAffine(12, fill="abc")
682-
683-
with pytest.raises(TypeError, match="Got inappropriate fill arg"):
684-
transforms.RandomAffine(12, fill="abc")
685-
686-
for kwargs in [
687-
{"center": 12},
688-
{"translate": 12},
689-
{"scale": 12},
690-
]:
691-
with pytest.raises(TypeError, match="should be a sequence of length"):
692-
transforms.RandomAffine(12, **kwargs)
693-
694-
for kwargs in [{"center": [1, 2, 3]}, {"translate": [1, 2, 3]}, {"scale": [1, 2, 3]}]:
695-
with pytest.raises(ValueError, match="should be a sequence of length"):
696-
transforms.RandomAffine(12, **kwargs)
697-
698-
with pytest.raises(ValueError, match="translation values should be between 0 and 1"):
699-
transforms.RandomAffine(12, translate=[-1.0, 2.0])
700-
701-
with pytest.raises(ValueError, match="scale values should be positive"):
702-
transforms.RandomAffine(12, scale=[-1.0, 2.0])
703-
704-
with pytest.raises(ValueError, match="is a single number, it must be positive"):
705-
transforms.RandomAffine(12, shear=-10)
706-
707-
for s in [[-0.7], [-0.7, 0, 0.7]]:
708-
with pytest.raises(ValueError, match="shear should be a sequence of length 2"):
709-
transforms.RandomAffine(12, shear=s)
710-
711-
@pytest.mark.parametrize("degrees", [23, [0, 45], (0, 45)])
712-
@pytest.mark.parametrize("translate", [None, [0.1, 0.2]])
713-
@pytest.mark.parametrize("scale", [None, [0.7, 1.2]])
714-
@pytest.mark.parametrize("shear", [None, 2.0, [5.0, 15.0], [1.0, 2.0, 3.0, 4.0]])
715-
def test__get_params(self, degrees, translate, scale, shear, mocker):
716-
image = mocker.MagicMock(spec=datapoints.Image)
717-
image.num_channels = 3
718-
image.spatial_size = (24, 32)
719-
h, w = image.spatial_size
720-
721-
transform = transforms.RandomAffine(degrees, translate=translate, scale=scale, shear=shear)
722-
params = transform._get_params([image])
723-
724-
if not isinstance(degrees, (list, tuple)):
725-
assert -degrees <= params["angle"] <= degrees
726-
else:
727-
assert degrees[0] <= params["angle"] <= degrees[1]
728-
729-
if translate is not None:
730-
w_max = int(round(translate[0] * w))
731-
h_max = int(round(translate[1] * h))
732-
assert -w_max <= params["translate"][0] <= w_max
733-
assert -h_max <= params["translate"][1] <= h_max
734-
else:
735-
assert params["translate"] == (0, 0)
736-
737-
if scale is not None:
738-
assert scale[0] <= params["scale"] <= scale[1]
739-
else:
740-
assert params["scale"] == 1.0
741-
742-
if shear is not None:
743-
if isinstance(shear, float):
744-
assert -shear <= params["shear"][0] <= shear
745-
assert params["shear"][1] == 0.0
746-
elif len(shear) == 2:
747-
assert shear[0] <= params["shear"][0] <= shear[1]
748-
assert params["shear"][1] == 0.0
749-
else:
750-
assert shear[0] <= params["shear"][0] <= shear[1]
751-
assert shear[2] <= params["shear"][1] <= shear[3]
752-
else:
753-
assert params["shear"] == (0, 0)
754-
755-
@pytest.mark.parametrize("degrees", [23, [0, 45], (0, 45)])
756-
@pytest.mark.parametrize("translate", [None, [0.1, 0.2]])
757-
@pytest.mark.parametrize("scale", [None, [0.7, 1.2]])
758-
@pytest.mark.parametrize("shear", [None, 2.0, [5.0, 15.0], [1.0, 2.0, 3.0, 4.0]])
759-
@pytest.mark.parametrize("fill", [0, [1, 2, 3], (2, 3, 4)])
760-
@pytest.mark.parametrize("center", [None, [2.0, 3.0]])
761-
def test__transform(self, degrees, translate, scale, shear, fill, center, mocker):
762-
interpolation = InterpolationMode.BILINEAR
763-
transform = transforms.RandomAffine(
764-
degrees,
765-
translate=translate,
766-
scale=scale,
767-
shear=shear,
768-
interpolation=interpolation,
769-
fill=fill,
770-
center=center,
771-
)
772-
773-
if isinstance(degrees, (tuple, list)):
774-
assert transform.degrees == [float(degrees[0]), float(degrees[1])]
775-
else:
776-
assert transform.degrees == [float(-degrees), float(degrees)]
777-
778-
fn = mocker.patch("torchvision.transforms.v2.functional.affine")
779-
inpt = mocker.MagicMock(spec=datapoints.Image)
780-
inpt.num_channels = 3
781-
inpt.spatial_size = (24, 32)
782-
783-
# vfdev-5, Feature Request: let's store params as Transform attribute
784-
# This could be also helpful for users
785-
# Otherwise, we can mock transform._get_params
786-
torch.manual_seed(12)
787-
_ = transform(inpt)
788-
torch.manual_seed(12)
789-
params = transform._get_params([inpt])
790-
791-
fill = transforms._utils._convert_fill_arg(fill)
792-
fn.assert_called_once_with(inpt, **params, interpolation=interpolation, fill=fill, center=center)
793-
794-
795671
class TestRandomCrop:
796672
def test_assertions(self):
797673
with pytest.raises(ValueError, match="Please provide only two dimensions"):

test/test_transforms_v2_functional.py

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -665,77 +665,6 @@ def _compute_affine_matrix(angle_, translate_, scale_, shear_, center_):
665665
return true_matrix
666666

667667

668-
@pytest.mark.parametrize("device", cpu_and_cuda())
669-
def test_correctness_affine_bounding_box_on_fixed_input(device):
670-
# Check transformation against known expected output
671-
format = datapoints.BoundingBoxFormat.XYXY
672-
spatial_size = (64, 64)
673-
in_boxes = [
674-
[20, 25, 35, 45],
675-
[50, 5, 70, 22],
676-
[spatial_size[1] // 2 - 10, spatial_size[0] // 2 - 10, spatial_size[1] // 2 + 10, spatial_size[0] // 2 + 10],
677-
[1, 1, 5, 5],
678-
]
679-
in_boxes = torch.tensor(in_boxes, dtype=torch.float64, device=device)
680-
# Tested parameters
681-
angle = 63
682-
scale = 0.89
683-
dx = 0.12
684-
dy = 0.23
685-
686-
# Expected bboxes computed using albumentations:
687-
# from albumentations.augmentations.geometric.functional import bbox_shift_scale_rotate
688-
# from albumentations.augmentations.geometric.functional import normalize_bbox, denormalize_bbox
689-
# expected_bboxes = []
690-
# for in_box in in_boxes:
691-
# n_in_box = normalize_bbox(in_box, *spatial_size)
692-
# n_out_box = bbox_shift_scale_rotate(n_in_box, -angle, scale, dx, dy, *spatial_size)
693-
# out_box = denormalize_bbox(n_out_box, *spatial_size)
694-
# expected_bboxes.append(out_box)
695-
expected_bboxes = [
696-
(24.522435977922218, 34.375689508290854, 46.443125279998114, 54.3516575015695),
697-
(54.88288587110401, 50.08453280875634, 76.44484547743795, 72.81332520036864),
698-
(27.709526487041554, 34.74952648704156, 51.650473512958435, 58.69047351295844),
699-
(48.56528888843238, 9.611532109828834, 53.35347829361575, 14.39972151501221),
700-
]
701-
702-
expected_bboxes = clamp_bounding_box(
703-
datapoints.BoundingBox(expected_bboxes, format="XYXY", spatial_size=spatial_size)
704-
).tolist()
705-
706-
output_boxes = F.affine_bounding_box(
707-
in_boxes,
708-
format=format,
709-
spatial_size=spatial_size,
710-
angle=angle,
711-
translate=(dx * spatial_size[1], dy * spatial_size[0]),
712-
scale=scale,
713-
shear=(0, 0),
714-
)
715-
716-
torch.testing.assert_close(output_boxes.tolist(), expected_bboxes)
717-
718-
719-
@pytest.mark.parametrize("device", cpu_and_cuda())
720-
def test_correctness_affine_segmentation_mask_on_fixed_input(device):
721-
# Check transformation against known expected output and CPU/CUDA devices
722-
723-
# Create a fixed input segmentation mask with 2 square masks
724-
# in top-left, bottom-left corners
725-
mask = torch.zeros(1, 32, 32, dtype=torch.long, device=device)
726-
mask[0, 2:10, 2:10] = 1
727-
mask[0, 32 - 9 : 32 - 3, 3:9] = 2
728-
729-
# Rotate 90 degrees and scale
730-
expected_mask = torch.rot90(mask, k=-1, dims=(-2, -1))
731-
expected_mask = torch.nn.functional.interpolate(expected_mask[None, :].float(), size=(64, 64), mode="nearest")
732-
expected_mask = expected_mask[0, :, 16 : 64 - 16, 16 : 64 - 16].long()
733-
734-
out_mask = F.affine_mask(mask, 90, [0.0, 0.0], 64.0 / 32.0, [0.0, 0.0])
735-
736-
torch.testing.assert_close(out_mask, expected_mask)
737-
738-
739668
@pytest.mark.parametrize("angle", range(-90, 90, 56))
740669
@pytest.mark.parametrize("expand, center", [(True, None), (False, None), (False, (12, 14))])
741670
def test_correctness_rotate_bounding_box(angle, expand, center):
@@ -950,18 +879,6 @@ def test_correctness_crop_bounding_box(device, format, top, left, height, width,
950879
torch.testing.assert_close(output_spatial_size, spatial_size)
951880

952881

953-
@pytest.mark.parametrize("device", cpu_and_cuda())
954-
def test_correctness_horizontal_flip_segmentation_mask_on_fixed_input(device):
955-
mask = torch.zeros((3, 3, 3), dtype=torch.long, device=device)
956-
mask[:, :, 0] = 1
957-
958-
out_mask = F.horizontal_flip_mask(mask)
959-
960-
expected_mask = torch.zeros((3, 3, 3), dtype=torch.long, device=device)
961-
expected_mask[:, :, -1] = 1
962-
torch.testing.assert_close(out_mask, expected_mask)
963-
964-
965882
@pytest.mark.parametrize("device", cpu_and_cuda())
966883
def test_correctness_vertical_flip_segmentation_mask_on_fixed_input(device):
967884
mask = torch.zeros((3, 3, 3), dtype=torch.long, device=device)

0 commit comments

Comments
 (0)