-
Notifications
You must be signed in to change notification settings - Fork 7.2k
Implement Flip transforms with CVCUDA backend #9277
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1249,6 +1249,10 @@ def test_kernel_video(self): | |
| def test_functional(self, make_input): | ||
| check_functional(F.horizontal_flip, make_input()) | ||
|
|
||
| @pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available") | ||
| def test_functional_cvcuda(self): | ||
| check_functional(F.horizontal_flip, make_image_cvcuda(batch_dims=(1,))) | ||
|
|
||
| @pytest.mark.parametrize( | ||
| ("kernel", "input_type"), | ||
| [ | ||
|
|
@@ -1291,6 +1295,15 @@ def test_image_correctness(self, fn): | |
|
|
||
| torch.testing.assert_close(actual, expected) | ||
|
|
||
| @pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available") | ||
| def test_image_correctness_cvcuda(self): | ||
|
Member
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 should be able to parametrize this test to control both the class and functional implementations as done for the the test @pytest.mark.parametrize(
"fn", [F.horizontal_flip, transform_cls_to_functional(transforms.RandomHorizontalFlip, p=1)]
)
Member
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 could also re-use the test @pytest.mark.parametrize(
"make_input",
[
make_image,
make_image_cvcuda,
],
) |
||
| image = make_image_cvcuda(batch_dims=(1,)) | ||
|
|
||
| actual = F.horizontal_flip(image) | ||
| expected_torch = F.horizontal_flip(F.cvcuda_to_tensor(image)) | ||
|
|
||
| assert torch.equal(F.cvcuda_to_tensor(actual), expected_torch) | ||
|
Member
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 can use
Member
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. Agreed, and for that we just use the plain
|
||
|
|
||
| def _reference_horizontal_flip_bounding_boxes(self, bounding_boxes: tv_tensors.BoundingBoxes): | ||
| affine_matrix = np.array( | ||
| [ | ||
|
|
@@ -1865,6 +1878,10 @@ def test_kernel_video(self): | |
| def test_functional(self, make_input): | ||
| check_functional(F.vertical_flip, make_input()) | ||
|
|
||
| @pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available") | ||
| def test_functional_cvcuda(self): | ||
| check_functional(F.vertical_flip, make_image_cvcuda()) | ||
|
|
||
| @pytest.mark.parametrize( | ||
| ("kernel", "input_type"), | ||
| [ | ||
|
|
@@ -1905,6 +1922,15 @@ def test_image_correctness(self, fn): | |
|
|
||
| torch.testing.assert_close(actual, expected) | ||
|
|
||
| @pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available") | ||
| def test_image_correctness_cvcuda(self): | ||
| image = make_image_cvcuda(batch_dims=(1,)) | ||
|
|
||
| actual = F.vertical_flip(image) | ||
| expected_torch = F.vertical_flip(F.cvcuda_to_tensor(image)) | ||
|
|
||
| assert torch.equal(F.cvcuda_to_tensor(actual), expected_torch) | ||
|
|
||
| def _reference_vertical_flip_bounding_boxes(self, bounding_boxes: tv_tensors.BoundingBoxes): | ||
| affine_matrix = np.array( | ||
| [ | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,7 +2,7 @@ | |||||
| import numbers | ||||||
| import warnings | ||||||
| from collections.abc import Sequence | ||||||
| from typing import Any, Optional, Union | ||||||
| from typing import Any, Optional, TYPE_CHECKING, Union | ||||||
|
|
||||||
| import PIL.Image | ||||||
| import torch | ||||||
|
|
@@ -26,7 +26,13 @@ | |||||
|
|
||||||
| from ._meta import _get_size_image_pil, clamp_bounding_boxes, convert_bounding_box_format | ||||||
|
|
||||||
| from ._utils import _FillTypeJIT, _get_kernel, _register_five_ten_crop_kernel_internal, _register_kernel_internal | ||||||
| from ._utils import _FillTypeJIT, _get_kernel, _import_cvcuda, _is_cvcuda_available, _register_five_ten_crop_kernel_internal, _register_kernel_internal | ||||||
|
|
||||||
| CVCUDA_AVAILABLE = _is_cvcuda_available() | ||||||
| if TYPE_CHECKING: | ||||||
| import cvcuda | ||||||
| if CVCUDA_AVAILABLE: | ||||||
| cvcuda = _import_cvcuda() | ||||||
|
|
||||||
|
|
||||||
| def _check_interpolation(interpolation: Union[InterpolationMode, int]) -> InterpolationMode: | ||||||
|
|
@@ -61,6 +67,12 @@ def horizontal_flip_image(image: torch.Tensor) -> torch.Tensor: | |||||
| def _horizontal_flip_image_pil(image: PIL.Image.Image) -> PIL.Image.Image: | ||||||
| return _FP.hflip(image) | ||||||
|
|
||||||
| def _horizontal_flip_image_cvcuda(image: "cvcuda.Tensor") -> "cvcuda.Tensor": | ||||||
|
Member
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. Should we expose this in "vision/torchvision/transforms/v2/functional/init.py"?
Member
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 don't need to. See how we're not exposing the PIL kernels there either. Users can just rely on the functionals for PIL and for CVCUDA. The main reason we expose the kernels is for when:
None of these apply to CV-CUDA (or for PIL). |
||||||
| return cvcuda.flip(image, flipCode=1) | ||||||
|
Member
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. Just going back on #9277 (comment) We'll want to explicitly use
|
||||||
|
|
||||||
|
|
||||||
| if CVCUDA_AVAILABLE: | ||||||
| _horizontal_flip_image_cvcuda_registered = _register_kernel_internal(horizontal_flip, cvcuda.Tensor)(_horizontal_flip_image_cvcuda) | ||||||
|
Member
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. To be extra safe this could be
Suggested change
|
||||||
|
|
||||||
| @_register_kernel_internal(horizontal_flip, tv_tensors.Mask) | ||||||
| def horizontal_flip_mask(mask: torch.Tensor) -> torch.Tensor: | ||||||
|
|
@@ -150,6 +162,14 @@ def _vertical_flip_image_pil(image: PIL.Image.Image) -> PIL.Image.Image: | |||||
| return _FP.vflip(image) | ||||||
|
|
||||||
|
|
||||||
| def _vertical_flip_image_cvcuda(image: "cvcuda.Tensor") -> "cvcuda.Tensor": | ||||||
| return cvcuda.flip(image, flipCode=0) | ||||||
|
|
||||||
|
|
||||||
| if CVCUDA_AVAILABLE: | ||||||
| _vertical_flip_image_cvcuda_registered = _register_kernel_internal(vertical_flip, cvcuda.Tensor)(_vertical_flip_image_cvcuda) | ||||||
|
|
||||||
|
|
||||||
| @_register_kernel_internal(vertical_flip, tv_tensors.Mask) | ||||||
| def vertical_flip_mask(mask: torch.Tensor) -> torch.Tensor: | ||||||
| return vertical_flip_image(mask) | ||||||
|
|
||||||
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.
You should be able to include this test as part of the generic
check_functionaltest above. You can simply addmake_image_cvcudato the list ofmake_inputpossible value in the@pytest.mark.parametrizedecorator.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.
We should also add a test for the kernel (similar to
test_kernel_image)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.
Similarly, let's make sure we add
make_image_cvcudato the list ofmake_inputpossible value in the@pytest.mark.parametrize decoratorfor the following tests:test_functional_signature,test_transform, andtest_transform_noop.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.
Agreed it should be parametrized. We still want to skip the test if cv-cuda isn't available, so I think it will look like: