Skip to content

Commit 98616f4

Browse files
committed
Update CVCUDA tests for horizontal and vertical flip and make changes according to the comments
1 parent 617079d commit 98616f4

File tree

3 files changed

+119
-20
lines changed

3 files changed

+119
-20
lines changed

test/test_transforms_v2.py

Lines changed: 86 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,10 @@ def test_kernel_video(self):
12401240
make_image_tensor,
12411241
make_image_pil,
12421242
make_image,
1243+
pytest.param(
1244+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
1245+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1246+
),
12431247
make_bounding_boxes,
12441248
make_segmentation_mask,
12451249
make_video,
@@ -1255,6 +1259,11 @@ def test_functional(self, make_input):
12551259
(F.horizontal_flip_image, torch.Tensor),
12561260
(F._geometry._horizontal_flip_image_pil, PIL.Image.Image),
12571261
(F.horizontal_flip_image, tv_tensors.Image),
1262+
pytest.param(
1263+
F._geometry._horizontal_flip_image_cvcuda,
1264+
cvcuda.Tensor,
1265+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1266+
),
12581267
(F.horizontal_flip_bounding_boxes, tv_tensors.BoundingBoxes),
12591268
(F.horizontal_flip_mask, tv_tensors.Mask),
12601269
(F.horizontal_flip_video, tv_tensors.Video),
@@ -1270,6 +1279,10 @@ def test_functional_signature(self, kernel, input_type):
12701279
make_image_tensor,
12711280
make_image_pil,
12721281
make_image,
1282+
pytest.param(
1283+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
1284+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1285+
),
12731286
make_bounding_boxes,
12741287
make_segmentation_mask,
12751288
make_video,
@@ -1283,13 +1296,32 @@ def test_transform(self, make_input, device):
12831296
@pytest.mark.parametrize(
12841297
"fn", [F.horizontal_flip, transform_cls_to_functional(transforms.RandomHorizontalFlip, p=1)]
12851298
)
1286-
def test_image_correctness(self, fn):
1287-
image = make_image(dtype=torch.uint8, device="cpu")
12881299

1289-
actual = fn(image)
1290-
expected = F.to_image(F.horizontal_flip(F.to_pil_image(image)))
1300+
@pytest.mark.parametrize(
1301+
"make_input",
1302+
[
1303+
make_image,
1304+
pytest.param(
1305+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
1306+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1307+
),
1308+
],
1309+
)
12911310

1292-
torch.testing.assert_close(actual, expected)
1311+
def test_image_correctness(self, fn, make_input):
1312+
image = make_input()
1313+
actual = fn(image)
1314+
if isinstance(image, cvcuda.Tensor):
1315+
# For CVCUDA input
1316+
expected = F.horizontal_flip(F.cvcuda_to_tensor(image))
1317+
print("actual is ", F.cvcuda_to_tensor(actual))
1318+
print("expected is ", expected)
1319+
assert_equal(F.cvcuda_to_tensor(actual), expected)
1320+
1321+
else:
1322+
# For PIL/regular image input
1323+
expected = F.to_image(F.horizontal_flip(F.to_pil_image(image)))
1324+
assert_equal(actual, expected)
12931325

12941326
def _reference_horizontal_flip_bounding_boxes(self, bounding_boxes: tv_tensors.BoundingBoxes):
12951327
affine_matrix = np.array(
@@ -1345,6 +1377,10 @@ def test_keypoints_correctness(self, fn):
13451377
make_image_tensor,
13461378
make_image_pil,
13471379
make_image,
1380+
pytest.param(
1381+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
1382+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1383+
),
13481384
make_bounding_boxes,
13491385
make_segmentation_mask,
13501386
make_video,
@@ -1354,12 +1390,13 @@ def test_keypoints_correctness(self, fn):
13541390
@pytest.mark.parametrize("device", cpu_and_cuda())
13551391
def test_transform_noop(self, make_input, device):
13561392
input = make_input(device=device)
1357-
13581393
transform = transforms.RandomHorizontalFlip(p=0)
1359-
13601394
output = transform(input)
1395+
if isinstance(input, cvcuda.Tensor):
1396+
assert_equal(F.cvcuda_to_tensor(output), F.cvcuda_to_tensor(input))
1397+
else:
1398+
assert_equal(output, input)
13611399

1362-
assert_equal(output, input)
13631400

13641401

13651402
class TestAffine:
@@ -1856,6 +1893,10 @@ def test_kernel_video(self):
18561893
make_image_tensor,
18571894
make_image_pil,
18581895
make_image,
1896+
pytest.param(
1897+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
1898+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1899+
),
18591900
make_bounding_boxes,
18601901
make_segmentation_mask,
18611902
make_video,
@@ -1871,6 +1912,11 @@ def test_functional(self, make_input):
18711912
(F.vertical_flip_image, torch.Tensor),
18721913
(F._geometry._vertical_flip_image_pil, PIL.Image.Image),
18731914
(F.vertical_flip_image, tv_tensors.Image),
1915+
pytest.param(
1916+
F._geometry._vertical_flip_image_cvcuda,
1917+
cvcuda.Tensor,
1918+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1919+
),
18741920
(F.vertical_flip_bounding_boxes, tv_tensors.BoundingBoxes),
18751921
(F.vertical_flip_mask, tv_tensors.Mask),
18761922
(F.vertical_flip_video, tv_tensors.Video),
@@ -1886,6 +1932,10 @@ def test_functional_signature(self, kernel, input_type):
18861932
make_image_tensor,
18871933
make_image_pil,
18881934
make_image,
1935+
pytest.param(
1936+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
1937+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1938+
),
18891939
make_bounding_boxes,
18901940
make_segmentation_mask,
18911941
make_video,
@@ -1897,13 +1947,28 @@ def test_transform(self, make_input, device):
18971947
check_transform(transforms.RandomVerticalFlip(p=1), make_input(device=device))
18981948

18991949
@pytest.mark.parametrize("fn", [F.vertical_flip, transform_cls_to_functional(transforms.RandomVerticalFlip, p=1)])
1900-
def test_image_correctness(self, fn):
1901-
image = make_image(dtype=torch.uint8, device="cpu")
1950+
@pytest.mark.parametrize(
1951+
"make_input",
1952+
[
1953+
make_image,
1954+
pytest.param(
1955+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
1956+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
1957+
),
1958+
],
1959+
)
19021960

1961+
def test_image_correctness(self, fn, make_input):
1962+
image = make_input()
19031963
actual = fn(image)
1904-
expected = F.to_image(F.vertical_flip(F.to_pil_image(image)))
1905-
1906-
torch.testing.assert_close(actual, expected)
1964+
if isinstance(image, cvcuda.Tensor):
1965+
# For CVCUDA input
1966+
expected = F.vertical_flip(F.cvcuda_to_tensor(image))
1967+
assert_equal(F.cvcuda_to_tensor(actual), expected)
1968+
else:
1969+
# For PIL/regular image input
1970+
expected = F.to_image(F.vertical_flip(F.to_pil_image(image)))
1971+
assert_equal(actual, expected)
19071972

19081973
def _reference_vertical_flip_bounding_boxes(self, bounding_boxes: tv_tensors.BoundingBoxes):
19091974
affine_matrix = np.array(
@@ -1955,6 +2020,10 @@ def test_keypoints_correctness(self, fn):
19552020
make_image_tensor,
19562021
make_image_pil,
19572022
make_image,
2023+
pytest.param(
2024+
functools.partial(make_image_cvcuda, batch_dims=(1,)),
2025+
marks=pytest.mark.skipif(not CVCUDA_AVAILABLE, reason="CVCUDA is not available"),
2026+
),
19582027
make_bounding_boxes,
19592028
make_segmentation_mask,
19602029
make_video,
@@ -1964,12 +2033,12 @@ def test_keypoints_correctness(self, fn):
19642033
@pytest.mark.parametrize("device", cpu_and_cuda())
19652034
def test_transform_noop(self, make_input, device):
19662035
input = make_input(device=device)
1967-
19682036
transform = transforms.RandomVerticalFlip(p=0)
1969-
19702037
output = transform(input)
1971-
1972-
assert_equal(output, input)
2038+
if isinstance(input, cvcuda.Tensor):
2039+
assert_equal(F.cvcuda_to_tensor(output), F.cvcuda_to_tensor(input))
2040+
else:
2041+
assert_equal(output, input)
19732042

19742043

19752044
class TestRotate:

torchvision/transforms/v2/_geometry.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from torchvision.ops.boxes import box_iou
1212
from torchvision.transforms.functional import _get_perspective_coeffs
1313
from torchvision.transforms.v2 import functional as F, InterpolationMode, Transform
14-
from torchvision.transforms.v2.functional._utils import _FillType
14+
from torchvision.transforms.v2.functional._utils import _FillType, _import_cvcuda, _is_cvcuda_available
1515

1616
from ._transform import _RandomApplyTransform
1717
from ._utils import (
@@ -30,6 +30,9 @@
3030
query_size,
3131
)
3232

33+
CVCUDA_AVAILABLE = _is_cvcuda_available()
34+
if CVCUDA_AVAILABLE:
35+
cvcuda = _import_cvcuda()
3336

3437
class RandomHorizontalFlip(_RandomApplyTransform):
3538
"""Horizontally flip the input with a given probability.
@@ -45,6 +48,9 @@ class RandomHorizontalFlip(_RandomApplyTransform):
4548

4649
_v1_transform_cls = _transforms.RandomHorizontalFlip
4750

51+
if CVCUDA_AVAILABLE:
52+
_transformed_types = (torch.Tensor, PIL.Image.Image, cvcuda.Tensor)
53+
4854
def transform(self, inpt: Any, params: dict[str, Any]) -> Any:
4955
return self._call_kernel(F.horizontal_flip, inpt)
5056

@@ -63,6 +69,10 @@ class RandomVerticalFlip(_RandomApplyTransform):
6369

6470
_v1_transform_cls = _transforms.RandomVerticalFlip
6571

72+
if CVCUDA_AVAILABLE:
73+
_transformed_types = (torch.Tensor, PIL.Image.Image, cvcuda.Tensor)
74+
75+
6676
def transform(self, inpt: Any, params: dict[str, Any]) -> Any:
6777
return self._call_kernel(F.vertical_flip, inpt)
6878

torchvision/transforms/v2/functional/_geometry.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import numbers
33
import warnings
44
from collections.abc import Sequence
5-
from typing import Any, Optional, Union
5+
from typing import Any, Optional, TYPE_CHECKING, Union
66

77
import PIL.Image
88
import torch
@@ -26,7 +26,13 @@
2626

2727
from ._meta import _get_size_image_pil, clamp_bounding_boxes, convert_bounding_box_format
2828

29-
from ._utils import _FillTypeJIT, _get_kernel, _register_five_ten_crop_kernel_internal, _register_kernel_internal
29+
from ._utils import _FillTypeJIT, _get_kernel, _import_cvcuda, _is_cvcuda_available, _register_five_ten_crop_kernel_internal, _register_kernel_internal
30+
31+
CVCUDA_AVAILABLE = _is_cvcuda_available()
32+
if TYPE_CHECKING:
33+
import cvcuda
34+
if CVCUDA_AVAILABLE:
35+
cvcuda = _import_cvcuda()
3036

3137

3238
def _check_interpolation(interpolation: Union[InterpolationMode, int]) -> InterpolationMode:
@@ -61,6 +67,12 @@ def horizontal_flip_image(image: torch.Tensor) -> torch.Tensor:
6167
def _horizontal_flip_image_pil(image: PIL.Image.Image) -> PIL.Image.Image:
6268
return _FP.hflip(image)
6369

70+
def _horizontal_flip_image_cvcuda(image: "cvcuda.Tensor") -> "cvcuda.Tensor":
71+
return _import_cvcuda().flip(image, flipCode=1)
72+
73+
74+
if CVCUDA_AVAILABLE:
75+
_horizontal_flip_image_cvcuda_registered = _register_kernel_internal(horizontal_flip, _import_cvcuda().Tensor)(_horizontal_flip_image_cvcuda)
6476

6577
@_register_kernel_internal(horizontal_flip, tv_tensors.Mask)
6678
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:
150162
return _FP.vflip(image)
151163

152164

165+
def _vertical_flip_image_cvcuda(image: "cvcuda.Tensor") -> "cvcuda.Tensor":
166+
return _import_cvcuda().flip(image, flipCode=0)
167+
168+
169+
if CVCUDA_AVAILABLE:
170+
_vertical_flip_image_cvcuda_registered = _register_kernel_internal(vertical_flip, _import_cvcuda().Tensor)(_vertical_flip_image_cvcuda)
171+
172+
153173
@_register_kernel_internal(vertical_flip, tv_tensors.Mask)
154174
def vertical_flip_mask(mask: torch.Tensor) -> torch.Tensor:
155175
return vertical_flip_image(mask)

0 commit comments

Comments
 (0)