Skip to content

Commit 91e8c66

Browse files
authored
Merge branch 'main' into fix-hardcoded-255
2 parents a400225 + add7596 commit 91e8c66

File tree

16 files changed

+157
-131
lines changed

16 files changed

+157
-131
lines changed

.github/workflows/test-linux-cpu.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
tests:
1717
strategy:
1818
matrix:
19-
py_vers: ["3.7", "3.8", "3.9", "3.10"]
19+
python_version: ["3.7", "3.8", "3.9", "3.10"]
2020
fail-fast: false
2121
uses: pytorch/test-infra/.github/workflows/linux_job.yml@main
2222
with:
@@ -27,7 +27,7 @@ jobs:
2727
git config --global --add safe.directory /__w/vision/vision
2828
2929
# Set up Environment Variables
30-
export PYTHON_VERSION="${{ matrix.py_vers }}"
30+
export PYTHON_VERSION="${{ matrix.python_version }}"
3131
export VERSION="cpu"
3232
export CUDATOOLKIT="cpuonly"
3333

.github/workflows/test-linux-gpu.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
name: Unit-tests on Linux GPU
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- nightly
8+
- main
9+
- release/*
10+
workflow_dispatch:
11+
12+
env:
13+
CHANNEL: "nightly"
14+
15+
jobs:
16+
tests:
17+
strategy:
18+
matrix:
19+
python_version: ["3.8"]
20+
cuda_arch_version: ["11.6"]
21+
fail-fast: false
22+
uses: pytorch/test-infra/.github/workflows/linux_job.yml@main
23+
with:
24+
runner: linux.g5.4xlarge.nvidia.gpu
25+
repository: pytorch/vision
26+
gpu-arch-type: cuda
27+
gpu-arch-version: ${{ matrix.cuda_arch_version }}
28+
timeout: 120
29+
script: |
30+
# Mark Build Directory Safe
31+
git config --global --add safe.directory /__w/vision/vision
32+
33+
# Set up Environment Variables
34+
export PYTHON_VERSION="${{ matrix.python_version }}"
35+
export VERSION="${{ matrix.cuda_arch_version }}"
36+
export CUDATOOLKIT="pytorch-cuda=${VERSION}"
37+
38+
# Set CHANNEL
39+
if [[ (${GITHUB_EVENT_NAME} = 'pull_request' && (${GITHUB_BASE_REF} = 'release'*)) || (${GITHUB_REF} = 'refs/heads/release'*) ]]; then
40+
export CHANNEL=test
41+
else
42+
export CHANNEL=nightly
43+
fi
44+
45+
# Create Conda Env
46+
conda create -yp ci_env python="${PYTHON_VERSION}" numpy libpng jpeg scipy
47+
conda activate /work/ci_env
48+
49+
# Install PyTorch, Torchvision, and testing libraries
50+
set -ex
51+
conda install \
52+
--yes \
53+
-c "pytorch-${CHANNEL}" \
54+
-c nvidia "pytorch-${CHANNEL}"::pytorch[build="*${VERSION}*"] \
55+
"${CUDATOOLKIT}"
56+
python3 setup.py develop
57+
python3 -m pip install pytest pytest-mock 'av<10'
58+
59+
# Run Tests
60+
python3 -m torch.utils.collect_env
61+
python3 -m pytest --junitxml=test-results/junit.xml -v --durations 20

test/prototype_transforms_kernel_infos.py

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import functools
33
import itertools
44
import math
5-
import re
65

76
import numpy as np
87
import pytest
@@ -159,12 +158,6 @@ def sample_inputs_horizontal_flip_video():
159158
KernelInfo(
160159
F.horizontal_flip_bounding_box,
161160
sample_inputs_fn=sample_inputs_horizontal_flip_bounding_box,
162-
test_marks=[
163-
TestMark(
164-
("TestKernels", "test_scripted_vs_eager"),
165-
pytest.mark.filterwarnings(f"ignore:{re.escape('operator() profile_node %72')}:UserWarning"),
166-
)
167-
],
168161
),
169162
KernelInfo(
170163
F.horizontal_flip_mask,
@@ -2045,17 +2038,11 @@ def sample_inputs_convert_dtype_video():
20452038
yield ArgsKwargs(video_loader)
20462039

20472040

2048-
_common_convert_dtype_marks = [
2049-
TestMark(
2050-
("TestKernels", "test_dtype_and_device_consistency"),
2051-
pytest.mark.skip(reason="`convert_dtype_*` kernels convert the dtype by design"),
2052-
condition=lambda args_kwargs: args_kwargs.args[0].dtype != args_kwargs.kwargs.get("dtype", torch.float32),
2053-
),
2054-
TestMark(
2055-
("TestKernels", "test_scripted_vs_eager"),
2056-
pytest.mark.filterwarnings(f"ignore:{re.escape('operator() profile_node %')}:UserWarning"),
2057-
),
2058-
]
2041+
skip_dtype_consistency = TestMark(
2042+
("TestKernels", "test_dtype_and_device_consistency"),
2043+
pytest.mark.skip(reason="`convert_dtype_*` kernels convert the dtype by design"),
2044+
condition=lambda args_kwargs: args_kwargs.args[0].dtype != args_kwargs.kwargs.get("dtype", torch.float32),
2045+
)
20592046

20602047
KERNEL_INFOS.extend(
20612048
[
@@ -2065,7 +2052,7 @@ def sample_inputs_convert_dtype_video():
20652052
reference_fn=reference_convert_dtype_image_tensor,
20662053
reference_inputs_fn=reference_inputs_convert_dtype_image_tensor,
20672054
test_marks=[
2068-
*_common_convert_dtype_marks,
2055+
skip_dtype_consistency,
20692056
TestMark(
20702057
("TestKernels", "test_against_reference"),
20712058
pytest.mark.xfail(reason="Conversion overflows"),
@@ -2083,7 +2070,9 @@ def sample_inputs_convert_dtype_video():
20832070
KernelInfo(
20842071
F.convert_dtype_video,
20852072
sample_inputs_fn=sample_inputs_convert_dtype_video,
2086-
test_marks=_common_convert_dtype_marks,
2073+
test_marks=[
2074+
skip_dtype_consistency,
2075+
],
20872076
),
20882077
]
20892078
)

test/test_prototype_transforms_functional.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import math
22
import os
3+
import re
34

45
import numpy as np
56
import PIL.Image
@@ -26,6 +27,15 @@ def script(fn):
2627
raise AssertionError(f"Trying to `torch.jit.script` '{fn.__name__}' raised the error above.") from error
2728

2829

30+
# Scripting a function often triggers a warning like
31+
# `UserWarning: operator() profile_node %$INT1 : int[] = prim::profile_ivalue($INT2) does not have profile information`
32+
# with varying `INT1` and `INT2`. Since these are uninteresting for us and only clutter the test summary, we ignore
33+
# them.
34+
ignore_jit_warning_no_profile = pytest.mark.filterwarnings(
35+
f"ignore:{re.escape('operator() profile_node %')}:UserWarning"
36+
)
37+
38+
2939
def make_info_args_kwargs_params(info, *, args_kwargs_fn, test_id=None):
3040
args_kwargs = list(args_kwargs_fn(info))
3141
idx_field_len = len(str(len(args_kwargs)))
@@ -87,6 +97,7 @@ class TestKernels:
8797
condition=lambda info: info.reference_fn is not None,
8898
)
8999

100+
@ignore_jit_warning_no_profile
90101
@sample_inputs
91102
@pytest.mark.parametrize("device", cpu_and_gpu())
92103
def test_scripted_vs_eager(self, info, args_kwargs, device):
@@ -218,6 +229,7 @@ class TestDispatchers:
218229
condition=lambda info: features.Image in info.kernels,
219230
)
220231

232+
@ignore_jit_warning_no_profile
221233
@image_sample_inputs
222234
@pytest.mark.parametrize("device", cpu_and_gpu())
223235
def test_scripted_smoke(self, info, args_kwargs, device):
@@ -230,6 +242,7 @@ def test_scripted_smoke(self, info, args_kwargs, device):
230242

231243
# TODO: We need this until the dispatchers below also have `DispatcherInfo`'s. If they do, `test_scripted_smoke`
232244
# replaces this test for them.
245+
@ignore_jit_warning_no_profile
233246
@pytest.mark.parametrize(
234247
"dispatcher",
235248
[
Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,7 @@
11
from ._bounding_box import BoundingBox, BoundingBoxFormat
22
from ._encoded import EncodedData, EncodedImage
33
from ._feature import _Feature, FillType, FillTypeJIT, InputType, InputTypeJIT, is_simple_tensor
4-
from ._image import (
5-
ColorSpace,
6-
Image,
7-
ImageType,
8-
ImageTypeJIT,
9-
LegacyImageType,
10-
LegacyImageTypeJIT,
11-
TensorImageType,
12-
TensorImageTypeJIT,
13-
)
4+
from ._image import ColorSpace, Image, ImageType, ImageTypeJIT, TensorImageType, TensorImageTypeJIT
145
from ._label import Label, OneHotLabel
156
from ._mask import Mask
16-
from ._video import (
17-
LegacyVideoType,
18-
LegacyVideoTypeJIT,
19-
TensorVideoType,
20-
TensorVideoTypeJIT,
21-
Video,
22-
VideoType,
23-
VideoTypeJIT,
24-
)
7+
from ._video import TensorVideoType, TensorVideoTypeJIT, Video, VideoType, VideoTypeJIT

torchvision/prototype/features/_bounding_box.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,6 @@ def wrap_like(
6161
def __repr__(self, *, tensor_contents: Any = None) -> str: # type: ignore[override]
6262
return self._make_repr(format=self.format, spatial_size=self.spatial_size)
6363

64-
def to_format(self, format: Union[str, BoundingBoxFormat]) -> BoundingBox:
65-
if isinstance(format, str):
66-
format = BoundingBoxFormat.from_str(format.upper())
67-
68-
return BoundingBox.wrap_like(
69-
self,
70-
self._F.convert_format_bounding_box(
71-
self.as_subclass(torch.Tensor), old_format=self.format, new_format=format
72-
),
73-
format=format,
74-
)
75-
7664
def horizontal_flip(self) -> BoundingBox:
7765
output = self._F.horizontal_flip_bounding_box(
7866
self.as_subclass(torch.Tensor), format=self.format, spatial_size=self.spatial_size

torchvision/prototype/features/_image.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import warnings
4-
from typing import Any, cast, List, Optional, Tuple, Union
4+
from typing import Any, List, Optional, Tuple, Union
55

66
import PIL.Image
77
import torch
@@ -104,7 +104,7 @@ def __repr__(self, *, tensor_contents: Any = None) -> str: # type: ignore[overr
104104

105105
@property
106106
def spatial_size(self) -> Tuple[int, int]:
107-
return cast(Tuple[int, int], tuple(self.shape[-2:]))
107+
return tuple(self.shape[-2:]) # type: ignore[return-value]
108108

109109
@property
110110
def num_channels(self) -> int:
@@ -285,7 +285,5 @@ def gaussian_blur(self, kernel_size: List[int], sigma: Optional[List[float]] = N
285285

286286
ImageType = Union[torch.Tensor, PIL.Image.Image, Image]
287287
ImageTypeJIT = torch.Tensor
288-
LegacyImageType = Union[torch.Tensor, PIL.Image.Image]
289-
LegacyImageTypeJIT = torch.Tensor
290288
TensorImageType = Union[torch.Tensor, Image]
291289
TensorImageTypeJIT = torch.Tensor

torchvision/prototype/features/_mask.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
from typing import Any, cast, List, Optional, Tuple, Union
3+
from typing import Any, List, Optional, Tuple, Union
44

55
import torch
66
from torchvision.transforms import InterpolationMode
@@ -34,7 +34,7 @@ def wrap_like(
3434

3535
@property
3636
def spatial_size(self) -> Tuple[int, int]:
37-
return cast(Tuple[int, int], tuple(self.shape[-2:]))
37+
return tuple(self.shape[-2:]) # type: ignore[return-value]
3838

3939
def horizontal_flip(self) -> Mask:
4040
output = self._F.horizontal_flip_mask(self.as_subclass(torch.Tensor))

torchvision/prototype/features/_video.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22

33
import warnings
4-
from typing import Any, cast, List, Optional, Tuple, Union
4+
from typing import Any, List, Optional, Tuple, Union
55

66
import torch
77
from torchvision.transforms.functional import InterpolationMode
@@ -56,7 +56,7 @@ def __repr__(self, *, tensor_contents: Any = None) -> str: # type: ignore[overr
5656

5757
@property
5858
def spatial_size(self) -> Tuple[int, int]:
59-
return cast(Tuple[int, int], tuple(self.shape[-2:]))
59+
return tuple(self.shape[-2:]) # type: ignore[return-value]
6060

6161
@property
6262
def num_channels(self) -> int:
@@ -237,7 +237,5 @@ def gaussian_blur(self, kernel_size: List[int], sigma: Optional[List[float]] = N
237237

238238
VideoType = Union[torch.Tensor, Video]
239239
VideoTypeJIT = torch.Tensor
240-
LegacyVideoType = torch.Tensor
241-
LegacyVideoTypeJIT = torch.Tensor
242240
TensorVideoType = Union[torch.Tensor, Video]
243241
TensorVideoTypeJIT = torch.Tensor

torchvision/prototype/transforms/_augment.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,24 +40,22 @@ def __init__(
4040
raise ValueError("Scale should be between 0 and 1")
4141
self.scale = scale
4242
self.ratio = ratio
43-
self.value = value
43+
if isinstance(value, (int, float)):
44+
self.value = [value]
45+
elif isinstance(value, str):
46+
self.value = None
47+
elif isinstance(value, tuple):
48+
self.value = list(value)
49+
else:
50+
self.value = value
4451
self.inplace = inplace
4552

4653
self._log_ratio = torch.log(torch.tensor(self.ratio))
4754

4855
def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]:
4956
img_c, img_h, img_w = query_chw(flat_inputs)
5057

51-
if isinstance(self.value, (int, float)):
52-
value = [self.value]
53-
elif isinstance(self.value, str):
54-
value = None
55-
elif isinstance(self.value, tuple):
56-
value = list(self.value)
57-
else:
58-
value = self.value
59-
60-
if value is not None and not (len(value) in (1, img_c)):
58+
if self.value is not None and not (len(self.value) in (1, img_c)):
6159
raise ValueError(
6260
f"If value is a sequence, it should have either a single value or {img_c} (number of inpt channels)"
6361
)
@@ -79,10 +77,10 @@ def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]:
7977
if not (h < img_h and w < img_w):
8078
continue
8179

82-
if value is None:
80+
if self.value is None:
8381
v = torch.empty([img_c, h, w], dtype=torch.float32).normal_()
8482
else:
85-
v = torch.tensor(value)[:, None, None]
83+
v = torch.tensor(self.value)[:, None, None]
8684

8785
i = torch.randint(0, img_h - h + 1, size=(1,)).item()
8886
j = torch.randint(0, img_w - w + 1, size=(1,)).item()
@@ -121,8 +119,7 @@ def _check_inputs(self, flat_inputs: List[Any]) -> None:
121119
def _mixup_onehotlabel(self, inpt: features.OneHotLabel, lam: float) -> features.OneHotLabel:
122120
if inpt.ndim < 2:
123121
raise ValueError("Need a batch of one hot labels")
124-
output = inpt.clone()
125-
output = output.roll(1, 0).mul_(1.0 - lam).add_(output.mul_(lam))
122+
output = inpt.roll(1, 0).mul_(1.0 - lam).add_(inpt.mul(lam))
126123
return features.OneHotLabel.wrap_like(inpt, output)
127124

128125

@@ -136,8 +133,7 @@ def _transform(self, inpt: Any, params: Dict[str, Any]) -> Any:
136133
expected_ndim = 5 if isinstance(inpt, features.Video) else 4
137134
if inpt.ndim < expected_ndim:
138135
raise ValueError("The transform expects a batched input")
139-
output = inpt.clone()
140-
output = output.roll(1, 0).mul_(1.0 - lam).add_(output.mul_(lam))
136+
output = inpt.roll(1, 0).mul_(1.0 - lam).add_(inpt.mul(lam))
141137

142138
if isinstance(inpt, (features.Image, features.Video)):
143139
output = type(inpt).wrap_like(inpt, output) # type: ignore[arg-type]
@@ -243,11 +239,12 @@ def _copy_paste(
243239
if blending:
244240
paste_alpha_mask = F.gaussian_blur(paste_alpha_mask.unsqueeze(0), kernel_size=[5, 5], sigma=[2.0])
245241

242+
inverse_paste_alpha_mask = paste_alpha_mask.logical_not()
246243
# Copy-paste images:
247-
image = (image * (~paste_alpha_mask)) + (paste_image * paste_alpha_mask)
244+
image = image.mul(inverse_paste_alpha_mask).add_(paste_image.mul(paste_alpha_mask))
248245

249246
# Copy-paste masks:
250-
masks = masks * (~paste_alpha_mask)
247+
masks = masks * inverse_paste_alpha_mask
251248
non_all_zero_masks = masks.sum((-1, -2)) > 0
252249
masks = masks[non_all_zero_masks]
253250

0 commit comments

Comments
 (0)