Unverified Commit ace92213 authored by Nicolas Hug's avatar Nicolas Hug Committed by GitHub
Browse files

Change antialias default from None to True (#7949)

parent 68fbd3c6
...@@ -59,7 +59,7 @@ def smoke_test_torchvision_resnet50_classify(device: str = "cpu") -> None: ...@@ -59,7 +59,7 @@ def smoke_test_torchvision_resnet50_classify(device: str = "cpu") -> None:
model.eval() model.eval()
# Step 2: Initialize the inference transforms # Step 2: Initialize the inference transforms
preprocess = weights.transforms() preprocess = weights.transforms(antialias=(device != "mps")) # antialias not supported on MPS
# Step 3: Apply inference preprocessing transforms # Step 3: Apply inference preprocessing transforms
batch = preprocess(img).unsqueeze(0) batch = preprocess(img).unsqueeze(0)
......
...@@ -2,7 +2,6 @@ import colorsys ...@@ -2,7 +2,6 @@ import colorsys
import itertools import itertools
import math import math
import os import os
import warnings
from functools import partial from functools import partial
from typing import Sequence from typing import Sequence
...@@ -569,23 +568,6 @@ def test_resize_antialias(device, dt, size, interpolation): ...@@ -569,23 +568,6 @@ def test_resize_antialias(device, dt, size, interpolation):
assert_equal(resized_tensor, resize_result) assert_equal(resized_tensor, resize_result)
def test_resize_antialias_default_warning():
img = torch.randint(0, 256, size=(3, 44, 56), dtype=torch.uint8)
match = "The default value of the antialias"
with pytest.warns(UserWarning, match=match):
F.resize(img, size=(20, 20))
with pytest.warns(UserWarning, match=match):
F.resized_crop(img, 0, 0, 10, 10, size=(20, 20))
# For modes that aren't bicubic or bilinear, don't throw a warning
with warnings.catch_warnings():
warnings.simplefilter("error")
F.resize(img, size=(20, 20), interpolation=NEAREST)
F.resized_crop(img, 0, 0, 10, 10, size=(20, 20), interpolation=NEAREST)
def check_functional_vs_PIL_vs_scripted( def check_functional_vs_PIL_vs_scripted(
fn, fn_pil, fn_t, config, device, dtype, channels=3, tol=2.0 + 1e-10, agg_method="max" fn, fn_pil, fn_t, config, device, dtype, channels=3, tol=2.0 + 1e-10, agg_method="max"
): ):
......
...@@ -1057,25 +1057,5 @@ def test_raft(model_fn, scripted): ...@@ -1057,25 +1057,5 @@ def test_raft(model_fn, scripted):
_assert_expected(flow_pred.cpu(), name=model_fn.__name__, atol=1e-2, rtol=1) _assert_expected(flow_pred.cpu(), name=model_fn.__name__, atol=1e-2, rtol=1)
def test_presets_antialias():
img = torch.randint(0, 256, size=(1, 3, 224, 224), dtype=torch.uint8)
match = "The default value of the antialias parameter"
with pytest.warns(UserWarning, match=match):
models.ResNet18_Weights.DEFAULT.transforms()(img)
with pytest.warns(UserWarning, match=match):
models.segmentation.DeepLabV3_ResNet50_Weights.DEFAULT.transforms()(img)
with warnings.catch_warnings():
warnings.simplefilter("error")
models.ResNet18_Weights.DEFAULT.transforms(antialias=True)(img)
models.segmentation.DeepLabV3_ResNet50_Weights.DEFAULT.transforms(antialias=True)(img)
models.detection.FasterRCNN_ResNet50_FPN_Weights.DEFAULT.transforms()(img)
models.video.R3D_18_Weights.DEFAULT.transforms()(img)
models.optical_flow.Raft_Small_Weights.DEFAULT.transforms()(img, img)
if __name__ == "__main__": if __name__ == "__main__":
pytest.main([__file__]) pytest.main([__file__])
...@@ -3,7 +3,6 @@ import os ...@@ -3,7 +3,6 @@ import os
import random import random
import re import re
import textwrap import textwrap
import warnings
from functools import partial from functools import partial
import numpy as np import numpy as np
...@@ -440,16 +439,6 @@ def test_resize_antialias_error(): ...@@ -440,16 +439,6 @@ def test_resize_antialias_error():
t(img) t(img)
def test_resize_antialias_default_warning():
img = Image.new("RGB", size=(10, 10), color=127)
# We make sure we don't warn for PIL images since the default behaviour doesn't change
with warnings.catch_warnings():
warnings.simplefilter("error")
transforms.Resize((20, 20))(img)
transforms.RandomResizedCrop((20, 20))(img)
@pytest.mark.parametrize("height, width", ((32, 64), (64, 32))) @pytest.mark.parametrize("height, width", ((32, 64), (64, 32)))
def test_resize_size_equals_small_edge_size(height, width): def test_resize_size_equals_small_edge_size(height, width):
# Non-regression test for https://github.com/pytorch/vision/issues/5405 # Non-regression test for https://github.com/pytorch/vision/issues/5405
......
import os import os
import sys import sys
import warnings
import numpy as np import numpy as np
import PIL.Image import PIL.Image
...@@ -428,22 +427,6 @@ class TestResize: ...@@ -428,22 +427,6 @@ class TestResize:
fn = T.RandomResizedCrop(size=[32], antialias=True) fn = T.RandomResizedCrop(size=[32], antialias=True)
_test_fn_save_load(fn, tmpdir) _test_fn_save_load(fn, tmpdir)
def test_antialias_default_warning(self):
img = torch.randint(0, 256, size=(3, 44, 56), dtype=torch.uint8)
match = "The default value of the antialias"
with pytest.warns(UserWarning, match=match):
T.Resize((20, 20))(img)
with pytest.warns(UserWarning, match=match):
T.RandomResizedCrop((20, 20))(img)
# For modes that aren't bicubic or bilinear, don't throw a warning
with warnings.catch_warnings():
warnings.simplefilter("error")
T.Resize((20, 20), interpolation=NEAREST)(img)
T.RandomResizedCrop((20, 20), interpolation=NEAREST)(img)
def _test_random_affine_helper(device, **kwargs): def _test_random_affine_helper(device, **kwargs):
tensor = torch.randint(0, 256, size=(3, 44, 56), dtype=torch.uint8, device=device) tensor = torch.randint(0, 256, size=(3, 44, 56), dtype=torch.uint8, device=device)
......
...@@ -2,7 +2,6 @@ import itertools ...@@ -2,7 +2,6 @@ import itertools
import pathlib import pathlib
import pickle import pickle
import random import random
import warnings
import numpy as np import numpy as np
...@@ -726,46 +725,6 @@ class TestUniformTemporalSubsample: ...@@ -726,46 +725,6 @@ class TestUniformTemporalSubsample:
assert output.dtype == inpt.dtype assert output.dtype == inpt.dtype
# TODO: remove this test in 0.17 when the default of antialias changes to True
def test_antialias_warning():
pil_img = PIL.Image.new("RGB", size=(10, 10), color=127)
tensor_img = torch.randint(0, 256, size=(3, 10, 10), dtype=torch.uint8)
tensor_video = torch.randint(0, 256, size=(2, 3, 10, 10), dtype=torch.uint8)
match = "The default value of the antialias parameter"
with pytest.warns(UserWarning, match=match):
transforms.RandomResizedCrop((20, 20))(tensor_img)
with pytest.warns(UserWarning, match=match):
transforms.ScaleJitter((20, 20))(tensor_img)
with pytest.warns(UserWarning, match=match):
transforms.RandomShortestSize((20, 20))(tensor_img)
with pytest.warns(UserWarning, match=match):
transforms.RandomResize(10, 20)(tensor_img)
with pytest.warns(UserWarning, match=match):
F.resized_crop(tv_tensors.Image(tensor_img), 0, 0, 10, 10, (20, 20))
with pytest.warns(UserWarning, match=match):
F.resize(tv_tensors.Video(tensor_video), (20, 20))
with pytest.warns(UserWarning, match=match):
F.resized_crop(tv_tensors.Video(tensor_video), 0, 0, 10, 10, (20, 20))
with warnings.catch_warnings():
warnings.simplefilter("error")
transforms.RandomResizedCrop((20, 20))(pil_img)
transforms.ScaleJitter((20, 20))(pil_img)
transforms.RandomShortestSize((20, 20))(pil_img)
transforms.RandomResize(10, 20)(pil_img)
transforms.RandomResizedCrop((20, 20), antialias=True)(tensor_img)
transforms.ScaleJitter((20, 20), antialias=True)(tensor_img)
transforms.RandomShortestSize((20, 20), antialias=True)(tensor_img)
transforms.RandomResize(10, 20, antialias=True)(tensor_img)
F.resized_crop(tv_tensors.Image(tensor_img), 0, 0, 10, 10, (20, 20), antialias=True)
F.resized_crop(tv_tensors.Video(tensor_video), 0, 0, 10, 10, (20, 20), antialias=True)
@pytest.mark.parametrize("image_type", (PIL.Image, torch.Tensor, tv_tensors.Image)) @pytest.mark.parametrize("image_type", (PIL.Image, torch.Tensor, tv_tensors.Image))
@pytest.mark.parametrize("label_type", (torch.Tensor, int)) @pytest.mark.parametrize("label_type", (torch.Tensor, int))
@pytest.mark.parametrize("dataset_return_type", (dict, tuple)) @pytest.mark.parametrize("dataset_return_type", (dict, tuple))
......
...@@ -19,7 +19,6 @@ import torchvision.ops ...@@ -19,7 +19,6 @@ import torchvision.ops
import torchvision.transforms.v2 as transforms import torchvision.transforms.v2 as transforms
from common_utils import ( from common_utils import (
assert_equal, assert_equal,
assert_no_warnings,
cache, cache,
cpu_and_cuda, cpu_and_cuda,
freeze_rng_state, freeze_rng_state,
...@@ -350,12 +349,6 @@ INTERPOLATION_MODES = [ ...@@ -350,12 +349,6 @@ INTERPOLATION_MODES = [
] ]
@contextlib.contextmanager
def assert_warns_antialias_default_value():
with pytest.warns(UserWarning, match="The default value of the antialias parameter of all the resizing transforms"):
yield
def reference_affine_bounding_boxes_helper(bounding_boxes, *, affine_matrix, new_canvas_size=None, clamp=True): def reference_affine_bounding_boxes_helper(bounding_boxes, *, affine_matrix, new_canvas_size=None, clamp=True):
format = bounding_boxes.format format = bounding_boxes.format
canvas_size = new_canvas_size or bounding_boxes.canvas_size canvas_size = new_canvas_size or bounding_boxes.canvas_size
...@@ -684,23 +677,6 @@ class TestResize: ...@@ -684,23 +677,6 @@ class TestResize:
with pytest.raises(ValueError, match=match): with pytest.raises(ValueError, match=match):
F.resize(make_input(self.INPUT_SIZE), size=size, max_size=max_size, antialias=True) F.resize(make_input(self.INPUT_SIZE), size=size, max_size=max_size, antialias=True)
@pytest.mark.parametrize("interpolation", INTERPOLATION_MODES)
@pytest.mark.parametrize(
"make_input",
[make_image_tensor, make_image, make_video],
)
def test_antialias_warning(self, interpolation, make_input):
with (
assert_warns_antialias_default_value()
if interpolation in {transforms.InterpolationMode.BILINEAR, transforms.InterpolationMode.BICUBIC}
else assert_no_warnings()
):
F.resize(
make_input(self.INPUT_SIZE),
size=self.OUTPUT_SIZES[0],
interpolation=interpolation,
)
@pytest.mark.parametrize("interpolation", INTERPOLATION_MODES) @pytest.mark.parametrize("interpolation", INTERPOLATION_MODES)
@pytest.mark.parametrize( @pytest.mark.parametrize(
"make_input", "make_input",
......
...@@ -440,9 +440,7 @@ def resize( ...@@ -440,9 +440,7 @@ def resize(
img: Tensor, img: Tensor,
size: List[int], size: List[int],
interpolation: str = "bilinear", interpolation: str = "bilinear",
# TODO: in v0.17, change the default to True. This will a private function antialias: Optional[bool] = True,
# by then, so we don't care about warning here.
antialias: Optional[bool] = None,
) -> Tensor: ) -> Tensor:
_assert_image_tensor(img) _assert_image_tensor(img)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
This file is part of the private API. Please do not use directly these classes as they will be modified on This file is part of the private API. Please do not use directly these classes as they will be modified on
future versions without warning. The classes should be accessed only via the transforms argument of Weights. future versions without warning. The classes should be accessed only via the transforms argument of Weights.
""" """
from typing import Optional, Tuple, Union from typing import Optional, Tuple
import torch import torch
from torch import nn, Tensor from torch import nn, Tensor
...@@ -44,7 +44,7 @@ class ImageClassification(nn.Module): ...@@ -44,7 +44,7 @@ class ImageClassification(nn.Module):
mean: Tuple[float, ...] = (0.485, 0.456, 0.406), mean: Tuple[float, ...] = (0.485, 0.456, 0.406),
std: Tuple[float, ...] = (0.229, 0.224, 0.225), std: Tuple[float, ...] = (0.229, 0.224, 0.225),
interpolation: InterpolationMode = InterpolationMode.BILINEAR, interpolation: InterpolationMode = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> None: ) -> None:
super().__init__() super().__init__()
self.crop_size = [crop_size] self.crop_size = [crop_size]
...@@ -151,7 +151,7 @@ class SemanticSegmentation(nn.Module): ...@@ -151,7 +151,7 @@ class SemanticSegmentation(nn.Module):
mean: Tuple[float, ...] = (0.485, 0.456, 0.406), mean: Tuple[float, ...] = (0.485, 0.456, 0.406),
std: Tuple[float, ...] = (0.229, 0.224, 0.225), std: Tuple[float, ...] = (0.229, 0.224, 0.225),
interpolation: InterpolationMode = InterpolationMode.BILINEAR, interpolation: InterpolationMode = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> None: ) -> None:
super().__init__() super().__init__()
self.resize_size = [resize_size] if resize_size is not None else None self.resize_size = [resize_size] if resize_size is not None else None
......
...@@ -393,19 +393,12 @@ def resize( ...@@ -393,19 +393,12 @@ def resize(
size: List[int], size: List[int],
interpolation: InterpolationMode = InterpolationMode.BILINEAR, interpolation: InterpolationMode = InterpolationMode.BILINEAR,
max_size: Optional[int] = None, max_size: Optional[int] = None,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> Tensor: ) -> Tensor:
r"""Resize the input image to the given size. r"""Resize the input image to the given size.
If the image is torch Tensor, it is expected If the image is torch Tensor, it is expected
to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions to have [..., H, W] shape, where ... means an arbitrary number of leading dimensions
.. warning::
The output image might be different depending on its type: when downsampling, the interpolation of PIL images
and tensors is slightly different, because PIL applies antialiasing. This may lead to significant differences
in the performance of a network. Therefore, it is preferable to train and serve a model with the same input
types. See also below the ``antialias`` parameter, which can help making the output of PIL images and tensors
closer.
Args: Args:
img (PIL Image or Tensor): Image to be resized. img (PIL Image or Tensor): Image to be resized.
size (sequence or int): Desired output size. If size is a sequence like size (sequence or int): Desired output size. If size is a sequence like
...@@ -437,7 +430,7 @@ def resize( ...@@ -437,7 +430,7 @@ def resize(
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -446,8 +439,8 @@ def resize( ...@@ -446,8 +439,8 @@ def resize(
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
Returns: Returns:
PIL Image or Tensor: Resized image. PIL Image or Tensor: Resized image.
...@@ -481,8 +474,6 @@ def resize( ...@@ -481,8 +474,6 @@ def resize(
if [image_height, image_width] == output_size: if [image_height, image_width] == output_size:
return img return img
antialias = _check_antialias(img, antialias, interpolation)
if not isinstance(img, torch.Tensor): if not isinstance(img, torch.Tensor):
if antialias is False: if antialias is False:
warnings.warn("Anti-alias option is always applied for PIL Image input. Argument antialias is ignored.") warnings.warn("Anti-alias option is always applied for PIL Image input. Argument antialias is ignored.")
...@@ -615,7 +606,7 @@ def resized_crop( ...@@ -615,7 +606,7 @@ def resized_crop(
width: int, width: int,
size: List[int], size: List[int],
interpolation: InterpolationMode = InterpolationMode.BILINEAR, interpolation: InterpolationMode = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> Tensor: ) -> Tensor:
"""Crop the given image and resize it to desired size. """Crop the given image and resize it to desired size.
If the image is torch Tensor, it is expected If the image is torch Tensor, it is expected
...@@ -643,7 +634,7 @@ def resized_crop( ...@@ -643,7 +634,7 @@ def resized_crop(
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -652,8 +643,8 @@ def resized_crop( ...@@ -652,8 +643,8 @@ def resized_crop(
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
Returns: Returns:
PIL Image or Tensor: Cropped image. PIL Image or Tensor: Cropped image.
""" """
...@@ -1590,28 +1581,3 @@ def elastic_transform( ...@@ -1590,28 +1581,3 @@ def elastic_transform(
if not isinstance(img, torch.Tensor): if not isinstance(img, torch.Tensor):
output = to_pil_image(output, mode=img.mode) output = to_pil_image(output, mode=img.mode)
return output return output
# TODO in v0.17: remove this helper and change default of antialias to True everywhere
def _check_antialias(
img: Tensor, antialias: Optional[Union[str, bool]], interpolation: InterpolationMode
) -> Optional[bool]:
if isinstance(antialias, str): # it should be "warn", but we don't bother checking against that
if isinstance(img, Tensor) and (
interpolation == InterpolationMode.BILINEAR or interpolation == InterpolationMode.BICUBIC
):
warnings.warn(
"The default value of the antialias parameter of all the resizing transforms "
"(Resize(), RandomResizedCrop(), etc.) "
"will change from None to True in v0.17, "
"in order to be consistent across the PIL and Tensor backends. "
"To suppress this warning, directly pass "
"antialias=True (recommended, future default), antialias=None (current default, "
"which means False for Tensors and True for PIL), "
"or antialias=False (only works on Tensors - PIL will still use antialiasing). "
"This also applies if you are using the inference transforms from the models weights: "
"update the call to weights.transforms(antialias=True)."
)
antialias = None
return antialias
...@@ -285,13 +285,6 @@ class Resize(torch.nn.Module): ...@@ -285,13 +285,6 @@ class Resize(torch.nn.Module):
If the image is torch Tensor, it is expected If the image is torch Tensor, it is expected
to have [..., H, W] shape, where ... means a maximum of two leading dimensions to have [..., H, W] shape, where ... means a maximum of two leading dimensions
.. warning::
The output image might be different depending on its type: when downsampling, the interpolation of PIL images
and tensors is slightly different, because PIL applies antialiasing. This may lead to significant differences
in the performance of a network. Therefore, it is preferable to train and serve a model with the same input
types. See also below the ``antialias`` parameter, which can help making the output of PIL images and tensors
closer.
Args: Args:
size (sequence or int): Desired output size. If size is a sequence like size (sequence or int): Desired output size. If size is a sequence like
(h, w), output size will be matched to this. If size is an int, (h, w), output size will be matched to this. If size is an int,
...@@ -321,7 +314,7 @@ class Resize(torch.nn.Module): ...@@ -321,7 +314,7 @@ class Resize(torch.nn.Module):
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -330,11 +323,11 @@ class Resize(torch.nn.Module): ...@@ -330,11 +323,11 @@ class Resize(torch.nn.Module):
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
""" """
def __init__(self, size, interpolation=InterpolationMode.BILINEAR, max_size=None, antialias="warn"): def __init__(self, size, interpolation=InterpolationMode.BILINEAR, max_size=None, antialias=True):
super().__init__() super().__init__()
_log_api_usage_once(self) _log_api_usage_once(self)
if not isinstance(size, (int, Sequence)): if not isinstance(size, (int, Sequence)):
...@@ -884,7 +877,7 @@ class RandomResizedCrop(torch.nn.Module): ...@@ -884,7 +877,7 @@ class RandomResizedCrop(torch.nn.Module):
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -893,8 +886,8 @@ class RandomResizedCrop(torch.nn.Module): ...@@ -893,8 +886,8 @@ class RandomResizedCrop(torch.nn.Module):
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
""" """
def __init__( def __init__(
...@@ -903,7 +896,7 @@ class RandomResizedCrop(torch.nn.Module): ...@@ -903,7 +896,7 @@ class RandomResizedCrop(torch.nn.Module):
scale=(0.08, 1.0), scale=(0.08, 1.0),
ratio=(3.0 / 4.0, 4.0 / 3.0), ratio=(3.0 / 4.0, 4.0 / 3.0),
interpolation=InterpolationMode.BILINEAR, interpolation=InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
): ):
super().__init__() super().__init__()
_log_api_usage_once(self) _log_api_usage_once(self)
......
...@@ -10,7 +10,6 @@ from torchvision import transforms as _transforms, tv_tensors ...@@ -10,7 +10,6 @@ from torchvision import transforms as _transforms, tv_tensors
from torchvision.ops.boxes import box_iou from torchvision.ops.boxes import box_iou
from torchvision.transforms.functional import _get_perspective_coeffs from torchvision.transforms.functional import _get_perspective_coeffs
from torchvision.transforms.v2 import functional as F, InterpolationMode, Transform from torchvision.transforms.v2 import functional as F, InterpolationMode, Transform
from torchvision.transforms.v2.functional._geometry import _check_interpolation
from torchvision.transforms.v2.functional._utils import _FillType from torchvision.transforms.v2.functional._utils import _FillType
from ._transform import _RandomApplyTransform from ._transform import _RandomApplyTransform
...@@ -81,13 +80,6 @@ class Resize(Transform): ...@@ -81,13 +80,6 @@ class Resize(Transform):
it can have arbitrary number of leading batch dimensions. For example, it can have arbitrary number of leading batch dimensions. For example,
the image can have ``[..., C, H, W]`` shape. A bounding box can have ``[..., 4]`` shape. the image can have ``[..., C, H, W]`` shape. A bounding box can have ``[..., 4]`` shape.
.. warning::
The output image might be different depending on its type: when downsampling, the interpolation of PIL images
and tensors is slightly different, because PIL applies antialiasing. This may lead to significant differences
in the performance of a network. Therefore, it is preferable to train and serve a model with the same input
types. See also below the ``antialias`` parameter, which can help making the output of PIL images and tensors
closer.
Args: Args:
size (sequence or int): Desired output size. If size is a sequence like size (sequence or int): Desired output size. If size is a sequence like
(h, w), output size will be matched to this. If size is an int, (h, w), output size will be matched to this. If size is an int,
...@@ -117,7 +109,7 @@ class Resize(Transform): ...@@ -117,7 +109,7 @@ class Resize(Transform):
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -126,8 +118,8 @@ class Resize(Transform): ...@@ -126,8 +118,8 @@ class Resize(Transform):
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
""" """
_v1_transform_cls = _transforms.Resize _v1_transform_cls = _transforms.Resize
...@@ -137,7 +129,7 @@ class Resize(Transform): ...@@ -137,7 +129,7 @@ class Resize(Transform):
size: Union[int, Sequence[int]], size: Union[int, Sequence[int]],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
max_size: Optional[int] = None, max_size: Optional[int] = None,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> None: ) -> None:
super().__init__() super().__init__()
...@@ -151,7 +143,7 @@ class Resize(Transform): ...@@ -151,7 +143,7 @@ class Resize(Transform):
) )
self.size = size self.size = size
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.max_size = max_size self.max_size = max_size
self.antialias = antialias self.antialias = antialias
...@@ -231,7 +223,7 @@ class RandomResizedCrop(Transform): ...@@ -231,7 +223,7 @@ class RandomResizedCrop(Transform):
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -240,8 +232,8 @@ class RandomResizedCrop(Transform): ...@@ -240,8 +232,8 @@ class RandomResizedCrop(Transform):
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
""" """
_v1_transform_cls = _transforms.RandomResizedCrop _v1_transform_cls = _transforms.RandomResizedCrop
...@@ -252,7 +244,7 @@ class RandomResizedCrop(Transform): ...@@ -252,7 +244,7 @@ class RandomResizedCrop(Transform):
scale: Tuple[float, float] = (0.08, 1.0), scale: Tuple[float, float] = (0.08, 1.0),
ratio: Tuple[float, float] = (3.0 / 4.0, 4.0 / 3.0), ratio: Tuple[float, float] = (3.0 / 4.0, 4.0 / 3.0),
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> None: ) -> None:
super().__init__() super().__init__()
self.size = _setup_size(size, error_msg="Please provide only two dimensions (h, w) for size.") self.size = _setup_size(size, error_msg="Please provide only two dimensions (h, w) for size.")
...@@ -268,7 +260,7 @@ class RandomResizedCrop(Transform): ...@@ -268,7 +260,7 @@ class RandomResizedCrop(Transform):
self.scale = scale self.scale = scale
self.ratio = ratio self.ratio = ratio
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.antialias = antialias self.antialias = antialias
self._log_ratio = torch.log(torch.tensor(self.ratio)) self._log_ratio = torch.log(torch.tensor(self.ratio))
...@@ -622,7 +614,7 @@ class RandomRotation(Transform): ...@@ -622,7 +614,7 @@ class RandomRotation(Transform):
) -> None: ) -> None:
super().__init__() super().__init__()
self.degrees = _setup_angle(degrees, name="degrees", req_sizes=(2,)) self.degrees = _setup_angle(degrees, name="degrees", req_sizes=(2,))
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.expand = expand self.expand = expand
self.fill = fill self.fill = fill
...@@ -724,7 +716,7 @@ class RandomAffine(Transform): ...@@ -724,7 +716,7 @@ class RandomAffine(Transform):
else: else:
self.shear = shear self.shear = shear
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.fill = fill self.fill = fill
self._fill = _setup_fill_arg(fill) self._fill = _setup_fill_arg(fill)
...@@ -969,7 +961,7 @@ class RandomPerspective(_RandomApplyTransform): ...@@ -969,7 +961,7 @@ class RandomPerspective(_RandomApplyTransform):
raise ValueError("Argument distortion_scale value should be between 0 and 1") raise ValueError("Argument distortion_scale value should be between 0 and 1")
self.distortion_scale = distortion_scale self.distortion_scale = distortion_scale
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.fill = fill self.fill = fill
self._fill = _setup_fill_arg(fill) self._fill = _setup_fill_arg(fill)
...@@ -1070,7 +1062,7 @@ class ElasticTransform(Transform): ...@@ -1070,7 +1062,7 @@ class ElasticTransform(Transform):
self.alpha = _setup_number_or_seq(alpha, "alpha") self.alpha = _setup_number_or_seq(alpha, "alpha")
self.sigma = _setup_number_or_seq(sigma, "sigma") self.sigma = _setup_number_or_seq(sigma, "sigma")
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.fill = fill self.fill = fill
self._fill = _setup_fill_arg(fill) self._fill = _setup_fill_arg(fill)
...@@ -1263,7 +1255,7 @@ class ScaleJitter(Transform): ...@@ -1263,7 +1255,7 @@ class ScaleJitter(Transform):
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -1272,8 +1264,8 @@ class ScaleJitter(Transform): ...@@ -1272,8 +1264,8 @@ class ScaleJitter(Transform):
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
""" """
def __init__( def __init__(
...@@ -1281,12 +1273,12 @@ class ScaleJitter(Transform): ...@@ -1281,12 +1273,12 @@ class ScaleJitter(Transform):
target_size: Tuple[int, int], target_size: Tuple[int, int],
scale_range: Tuple[float, float] = (0.1, 2.0), scale_range: Tuple[float, float] = (0.1, 2.0),
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
): ):
super().__init__() super().__init__()
self.target_size = target_size self.target_size = target_size
self.scale_range = scale_range self.scale_range = scale_range
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.antialias = antialias self.antialias = antialias
def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]: def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]:
...@@ -1330,7 +1322,7 @@ class RandomShortestSize(Transform): ...@@ -1330,7 +1322,7 @@ class RandomShortestSize(Transform):
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -1339,8 +1331,8 @@ class RandomShortestSize(Transform): ...@@ -1339,8 +1331,8 @@ class RandomShortestSize(Transform):
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
""" """
def __init__( def __init__(
...@@ -1348,12 +1340,12 @@ class RandomShortestSize(Transform): ...@@ -1348,12 +1340,12 @@ class RandomShortestSize(Transform):
min_size: Union[List[int], Tuple[int], int], min_size: Union[List[int], Tuple[int], int],
max_size: Optional[int] = None, max_size: Optional[int] = None,
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
): ):
super().__init__() super().__init__()
self.min_size = [min_size] if isinstance(min_size, int) else list(min_size) self.min_size = [min_size] if isinstance(min_size, int) else list(min_size)
self.max_size = max_size self.max_size = max_size
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.antialias = antialias self.antialias = antialias
def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]: def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]:
...@@ -1411,7 +1403,7 @@ class RandomResize(Transform): ...@@ -1411,7 +1403,7 @@ class RandomResize(Transform):
tensors), antialiasing makes no sense and this parameter is ignored. tensors), antialiasing makes no sense and this parameter is ignored.
Possible values are: Possible values are:
- ``True``: will apply antialiasing for bilinear or bicubic modes. - ``True`` (default): will apply antialiasing for bilinear or bicubic modes.
Other mode aren't affected. This is probably what you want to use. Other mode aren't affected. This is probably what you want to use.
- ``False``: will not apply antialiasing for tensors on any mode. PIL - ``False``: will not apply antialiasing for tensors on any mode. PIL
images are still antialiased on bilinear or bicubic modes, because images are still antialiased on bilinear or bicubic modes, because
...@@ -1420,8 +1412,8 @@ class RandomResize(Transform): ...@@ -1420,8 +1412,8 @@ class RandomResize(Transform):
PIL images. This value exists for legacy reasons and you probably PIL images. This value exists for legacy reasons and you probably
don't want to use it unless you really know what you are doing. don't want to use it unless you really know what you are doing.
The current default is ``None`` **but will change to** ``True`` **in The default value changed from ``None`` to ``True`` in
v0.17** for the PIL and Tensor backends to be consistent. v0.17, for the PIL and Tensor backends to be consistent.
""" """
def __init__( def __init__(
...@@ -1429,12 +1421,12 @@ class RandomResize(Transform): ...@@ -1429,12 +1421,12 @@ class RandomResize(Transform):
min_size: int, min_size: int,
max_size: int, max_size: int,
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> None: ) -> None:
super().__init__() super().__init__()
self.min_size = min_size self.min_size = min_size
self.max_size = max_size self.max_size = max_size
self.interpolation = _check_interpolation(interpolation) self.interpolation = interpolation
self.antialias = antialias self.antialias = antialias
def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]: def _get_params(self, flat_inputs: List[Any]) -> Dict[str, Any]:
......
...@@ -11,7 +11,6 @@ from torchvision import tv_tensors ...@@ -11,7 +11,6 @@ from torchvision import tv_tensors
from torchvision.transforms import _functional_pil as _FP from torchvision.transforms import _functional_pil as _FP
from torchvision.transforms._functional_tensor import _pad_symmetric from torchvision.transforms._functional_tensor import _pad_symmetric
from torchvision.transforms.functional import ( from torchvision.transforms.functional import (
_check_antialias,
_compute_resized_output_size as __compute_resized_output_size, _compute_resized_output_size as __compute_resized_output_size,
_get_perspective_coeffs, _get_perspective_coeffs,
_interpolation_modes_from_int, _interpolation_modes_from_int,
...@@ -177,7 +176,7 @@ def resize( ...@@ -177,7 +176,7 @@ def resize(
size: List[int], size: List[int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
max_size: Optional[int] = None, max_size: Optional[int] = None,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> torch.Tensor: ) -> torch.Tensor:
"""[BETA] See :class:`~torchvision.transforms.v2.Resize` for details.""" """[BETA] See :class:`~torchvision.transforms.v2.Resize` for details."""
if torch.jit.is_scripting(): if torch.jit.is_scripting():
...@@ -196,17 +195,15 @@ def resize_image( ...@@ -196,17 +195,15 @@ def resize_image(
size: List[int], size: List[int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
max_size: Optional[int] = None, max_size: Optional[int] = None,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> torch.Tensor: ) -> torch.Tensor:
interpolation = _check_interpolation(interpolation) interpolation = _check_interpolation(interpolation)
antialias = _check_antialias(img=image, antialias=antialias, interpolation=interpolation)
assert not isinstance(antialias, str)
antialias = False if antialias is None else antialias antialias = False if antialias is None else antialias
align_corners: Optional[bool] = None align_corners: Optional[bool] = None
if interpolation == InterpolationMode.BILINEAR or interpolation == InterpolationMode.BICUBIC: if interpolation == InterpolationMode.BILINEAR or interpolation == InterpolationMode.BICUBIC:
align_corners = False align_corners = False
else: else:
# The default of antialias should be True from 0.17, so we don't warn or # The default of antialias is True from 0.17, so we don't warn or
# error if other interpolation modes are used. This is documented. # error if other interpolation modes are used. This is documented.
antialias = False antialias = False
...@@ -297,7 +294,7 @@ def __resize_image_pil_dispatch( ...@@ -297,7 +294,7 @@ def __resize_image_pil_dispatch(
size: Union[Sequence[int], int], size: Union[Sequence[int], int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
max_size: Optional[int] = None, max_size: Optional[int] = None,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> PIL.Image.Image: ) -> PIL.Image.Image:
if antialias is False: if antialias is False:
warnings.warn("Anti-alias option is always applied for PIL Image input. Argument antialias is ignored.") warnings.warn("Anti-alias option is always applied for PIL Image input. Argument antialias is ignored.")
...@@ -361,7 +358,7 @@ def resize_video( ...@@ -361,7 +358,7 @@ def resize_video(
size: List[int], size: List[int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
max_size: Optional[int] = None, max_size: Optional[int] = None,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> torch.Tensor: ) -> torch.Tensor:
return resize_image(video, size=size, interpolation=interpolation, max_size=max_size, antialias=antialias) return resize_image(video, size=size, interpolation=interpolation, max_size=max_size, antialias=antialias)
...@@ -2066,7 +2063,7 @@ def resized_crop( ...@@ -2066,7 +2063,7 @@ def resized_crop(
width: int, width: int,
size: List[int], size: List[int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> torch.Tensor: ) -> torch.Tensor:
"""[BETA] See :class:`~torchvision.transforms.v2.RandomResizedCrop` for details.""" """[BETA] See :class:`~torchvision.transforms.v2.RandomResizedCrop` for details."""
if torch.jit.is_scripting(): if torch.jit.is_scripting():
...@@ -2106,7 +2103,7 @@ def resized_crop_image( ...@@ -2106,7 +2103,7 @@ def resized_crop_image(
width: int, width: int,
size: List[int], size: List[int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> torch.Tensor: ) -> torch.Tensor:
image = crop_image(image, top, left, height, width) image = crop_image(image, top, left, height, width)
return resize_image(image, size, interpolation=interpolation, antialias=antialias) return resize_image(image, size, interpolation=interpolation, antialias=antialias)
...@@ -2134,7 +2131,7 @@ def _resized_crop_image_pil_dispatch( ...@@ -2134,7 +2131,7 @@ def _resized_crop_image_pil_dispatch(
width: int, width: int,
size: List[int], size: List[int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> PIL.Image.Image: ) -> PIL.Image.Image:
if antialias is False: if antialias is False:
warnings.warn("Anti-alias option is always applied for PIL Image input. Argument antialias is ignored.") warnings.warn("Anti-alias option is always applied for PIL Image input. Argument antialias is ignored.")
...@@ -2203,7 +2200,7 @@ def resized_crop_video( ...@@ -2203,7 +2200,7 @@ def resized_crop_video(
width: int, width: int,
size: List[int], size: List[int],
interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR, interpolation: Union[InterpolationMode, int] = InterpolationMode.BILINEAR,
antialias: Optional[Union[str, bool]] = "warn", antialias: Optional[bool] = True,
) -> torch.Tensor: ) -> torch.Tensor:
return resized_crop_image( return resized_crop_image(
video, top, left, height, width, antialias=antialias, size=size, interpolation=interpolation video, top, left, height, width, antialias=antialias, size=size, interpolation=interpolation
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment