-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
port affine tests #7708
Merged
Merged
port affine tests #7708
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
0ee347e
port affine tests
pmeier b18d531
add remaining tests
pmeier 76fc367
Merge branch 'main' into port/affine
pmeier 262e9c2
Merge branch 'main' into port/affine
pmeier 39b91c8
break down massive parametrizations
pmeier 5520fdd
[PoC] re-unify kernel tests
pmeier 2619a34
[PoC] make affine params explicit in the parametrization
pmeier ae089a8
[PoC] fix
pmeier 980e77b
address review
pmeier File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,8 @@ | |
) | ||
from torch.testing import assert_close | ||
from torchvision import datapoints | ||
|
||
from torchvision.transforms._functional_tensor import _max_value as get_max_value | ||
from torchvision.transforms.functional import pil_modes_mapping | ||
from torchvision.transforms.v2 import functional as F | ||
|
||
|
@@ -473,10 +475,9 @@ def test_kernel_bounding_box(self, format, size, use_max_size, dtype, device): | |
) | ||
|
||
@pytest.mark.parametrize( | ||
"dtype_and_make_mask", [(torch.uint8, make_segmentation_mask), (torch.bool, make_detection_mask)] | ||
("dtype", "make_mask"), [(torch.uint8, make_segmentation_mask), (torch.bool, make_detection_mask)] | ||
) | ||
def test_kernel_mask(self, dtype_and_make_mask): | ||
dtype, make_mask = dtype_and_make_mask | ||
def test_kernel_mask(self, dtype, make_mask): | ||
check_kernel(F.resize_mask, make_mask(dtype=dtype), size=self.OUTPUT_SIZES[-1]) | ||
|
||
def test_kernel_video(self): | ||
|
@@ -744,7 +745,7 @@ def _make_input(self, input_type, *, dtype=None, device="cpu", spatial_size=(17, | |
@pytest.mark.parametrize("dtype", [torch.float32, torch.uint8]) | ||
@pytest.mark.parametrize("device", cpu_and_cuda()) | ||
def test_kernel_image_tensor(self, dtype, device): | ||
check_kernel(F.horizontal_flip_image_tensor, self._make_input(torch.Tensor)) | ||
check_kernel(F.horizontal_flip_image_tensor, self._make_input(torch.Tensor, dtype=dtype, device=device)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We didn't spot that before |
||
|
||
@pytest.mark.parametrize("format", list(datapoints.BoundingBoxFormat)) | ||
@pytest.mark.parametrize("dtype", [torch.float32, torch.int64]) | ||
|
@@ -860,3 +861,191 @@ def test_transform_noop(self, input_type, device): | |
output = transform(input) | ||
|
||
assert_equal(output, input) | ||
|
||
|
||
class TestAffine: | ||
def _make_input( | ||
self, input_type, *, dtype=None, device="cpu", spatial_size=(17, 11), mask_type="segmentation", **kwargs | ||
): | ||
if input_type in {torch.Tensor, PIL.Image.Image, datapoints.Image}: | ||
input = make_image(size=spatial_size, dtype=dtype or torch.uint8, device=device, **kwargs) | ||
if input_type is torch.Tensor: | ||
input = input.as_subclass(torch.Tensor) | ||
elif input_type is PIL.Image.Image: | ||
input = F.to_image_pil(input) | ||
elif input_type is datapoints.BoundingBox: | ||
kwargs.setdefault("format", datapoints.BoundingBoxFormat.XYXY) | ||
input = make_bounding_box( | ||
dtype=dtype or torch.float32, | ||
device=device, | ||
spatial_size=spatial_size, | ||
**kwargs, | ||
) | ||
elif input_type is datapoints.Mask: | ||
if mask_type == "segmentation": | ||
make_mask = make_segmentation_mask | ||
default_dtype = torch.uint8 | ||
elif mask_type == "detection": | ||
make_mask = make_detection_mask | ||
default_dtype = torch.bool | ||
input = make_mask(size=spatial_size, dtype=dtype or default_dtype, device=device, **kwargs) | ||
elif input_type is datapoints.Video: | ||
input = make_video(size=spatial_size, dtype=dtype or torch.uint8, device=device, **kwargs) | ||
|
||
return input | ||
|
||
def _adapt_fill_for_int_dtype(self, value, *, dtype): | ||
if value is None or dtype.is_floating_point: | ||
return value | ||
|
||
max_value = get_max_value(dtype) | ||
|
||
if isinstance(value, (int, float)): | ||
return type(value)(value * max_value) | ||
elif isinstance(value, (list, tuple)): | ||
return type(value)(type(v)(v * max_value) for v in value) | ||
|
||
@pytest.mark.parametrize("angle", [1.0, 2]) | ||
@pytest.mark.parametrize("translate", [[1.0, 0.5], [1, 2], (1.0, 0.5), (1, 2)]) | ||
@pytest.mark.parametrize("scale", [0.5]) | ||
@pytest.mark.parametrize("shear", [1.0, 2, [1.0], [2], (1.0,), (2,), [1.0, 0.5], [1, 2], (1.0, 0.5), (1, 2)]) | ||
@pytest.mark.parametrize( | ||
"interpolation", [transforms.InterpolationMode.NEAREST, transforms.InterpolationMode.BILINEAR] | ||
) | ||
@pytest.mark.parametrize( | ||
"fill", [None, 1, 0.5, [1], [0.5], (1,), (0.5,), [1, 0, 1], [0.1, 0.2, 0.3], (1, 0, 1), (0.1, 0.2, 0.3)] | ||
) | ||
@pytest.mark.parametrize("center", [None, [1.0, 0.5], [1, 2], (1.0, 0.5), (1, 2)]) | ||
@pytest.mark.parametrize("dtype", [torch.float32, torch.uint8]) | ||
@pytest.mark.parametrize("device", cpu_and_cuda()) | ||
pmeier marked this conversation as resolved.
Show resolved
Hide resolved
|
||
def test_kernel_image_tensor(self, angle, translate, scale, shear, interpolation, fill, center, dtype, device): | ||
check_kernel( | ||
F.affine_image_tensor, | ||
self._make_input(torch.Tensor, dtype=dtype, device=device), | ||
angle=angle, | ||
translate=translate, | ||
scale=scale, | ||
shear=shear, | ||
center=center, | ||
interpolation=interpolation, | ||
fill=self._adapt_fill_for_int_dtype(fill, dtype=dtype), | ||
check_scripted_vs_eager=not (isinstance(shear, (int, float)) or isinstance(fill, (int, float))), | ||
check_cuda_vs_cpu=dict(atol=1, rtol=0) | ||
if dtype is torch.uint8 and interpolation is transforms.InterpolationMode.BILINEAR | ||
else True, | ||
) | ||
|
||
# @pytest.mark.parametrize("format", list(datapoints.BoundingBoxFormat)) | ||
# @pytest.mark.parametrize("dtype", [torch.float32, torch.int64]) | ||
# @pytest.mark.parametrize("device", cpu_and_cuda()) | ||
# def test_kernel_bounding_box(self, format, dtype, device): | ||
# bounding_box = self._make_input(datapoints.BoundingBox, dtype=dtype, device=device, format=format) | ||
# check_kernel( | ||
# F.horizontal_flip_bounding_box, | ||
# bounding_box, | ||
# format=format, | ||
# spatial_size=bounding_box.spatial_size, | ||
# ) | ||
# | ||
# @pytest.mark.parametrize( | ||
# "dtype_and_make_mask", [(torch.uint8, make_segmentation_mask), (torch.bool, make_detection_mask)] | ||
# ) | ||
# def test_kernel_mask(self, dtype_and_make_mask): | ||
# dtype, make_mask = dtype_and_make_mask | ||
# check_kernel(F.horizontal_flip_mask, make_mask(dtype=dtype)) | ||
# | ||
# def test_kernel_video(self): | ||
# check_kernel(F.horizontal_flip_video, self._make_input(datapoints.Video)) | ||
# | ||
# @pytest.mark.parametrize( | ||
# ("input_type", "kernel"), | ||
# [ | ||
# (torch.Tensor, F.horizontal_flip_image_tensor), | ||
# (PIL.Image.Image, F.horizontal_flip_image_pil), | ||
# (datapoints.Image, F.horizontal_flip_image_tensor), | ||
# (datapoints.BoundingBox, F.horizontal_flip_bounding_box), | ||
# (datapoints.Mask, F.horizontal_flip_mask), | ||
# (datapoints.Video, F.horizontal_flip_video), | ||
# ], | ||
# ) | ||
# def test_dispatcher(self, kernel, input_type): | ||
# check_dispatcher(F.horizontal_flip, kernel, self._make_input(input_type)) | ||
# | ||
# @pytest.mark.parametrize( | ||
# ("input_type", "kernel"), | ||
# [ | ||
# (torch.Tensor, F.resize_image_tensor), | ||
# (PIL.Image.Image, F.resize_image_pil), | ||
# (datapoints.Image, F.resize_image_tensor), | ||
# (datapoints.BoundingBox, F.resize_bounding_box), | ||
# (datapoints.Mask, F.resize_mask), | ||
# (datapoints.Video, F.resize_video), | ||
# ], | ||
# ) | ||
# def test_dispatcher_signature(self, kernel, input_type): | ||
# check_dispatcher_signatures_match(F.resize, kernel=kernel, input_type=input_type) | ||
# | ||
# @pytest.mark.parametrize( | ||
# "input_type", | ||
# [torch.Tensor, PIL.Image.Image, datapoints.Image, datapoints.BoundingBox, datapoints.Mask, datapoints.Video], | ||
# ) | ||
# @pytest.mark.parametrize("device", cpu_and_cuda()) | ||
# def test_transform(self, input_type, device): | ||
# input = self._make_input(input_type, device=device) | ||
# | ||
# check_transform(transforms.RandomHorizontalFlip, input, p=1) | ||
# | ||
# @pytest.mark.parametrize( | ||
# "fn", [F.horizontal_flip, transform_cls_to_functional(transforms.RandomHorizontalFlip, p=1)] | ||
# ) | ||
# def test_image_correctness(self, fn): | ||
# image = self._make_input(torch.Tensor, dtype=torch.uint8, device="cpu") | ||
# | ||
# actual = fn(image) | ||
# expected = F.to_image_tensor(F.horizontal_flip(F.to_image_pil(image))) | ||
# | ||
# torch.testing.assert_close(actual, expected) | ||
# | ||
# def _reference_horizontal_flip_bounding_box(self, bounding_box): | ||
# affine_matrix = np.array( | ||
# [ | ||
# [-1, 0, bounding_box.spatial_size[1]], | ||
# [0, 1, 0], | ||
# ], | ||
# dtype="float64" if bounding_box.dtype == torch.float64 else "float32", | ||
# ) | ||
# | ||
# expected_bboxes = reference_affine_bounding_box_helper( | ||
# bounding_box, | ||
# format=bounding_box.format, | ||
# spatial_size=bounding_box.spatial_size, | ||
# affine_matrix=affine_matrix, | ||
# ) | ||
# | ||
# return datapoints.BoundingBox.wrap_like(bounding_box, expected_bboxes) | ||
# | ||
# @pytest.mark.parametrize("format", list(datapoints.BoundingBoxFormat)) | ||
# @pytest.mark.parametrize( | ||
# "fn", [F.horizontal_flip, transform_cls_to_functional(transforms.RandomHorizontalFlip, p=1)] | ||
# ) | ||
# def test_bounding_box_correctness(self, format, fn): | ||
# bounding_box = self._make_input(datapoints.BoundingBox) | ||
# | ||
# actual = fn(bounding_box) | ||
# expected = self._reference_horizontal_flip_bounding_box(bounding_box) | ||
# | ||
# torch.testing.assert_close(actual, expected) | ||
# | ||
# @pytest.mark.parametrize( | ||
# "input_type", | ||
# [torch.Tensor, PIL.Image.Image, datapoints.Image, datapoints.BoundingBox, datapoints.Mask, datapoints.Video], | ||
# ) | ||
# @pytest.mark.parametrize("device", cpu_and_cuda()) | ||
# def test_transform_noop(self, input_type, device): | ||
# input = self._make_input(input_type, device=device) | ||
# | ||
# transform = transforms.RandomHorizontalFlip(p=0) | ||
# | ||
# output = transform(input) | ||
# | ||
# assert_equal(output, input) |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QoL