Skip to content

Commit

Permalink
Merge branch 'main'
Browse files Browse the repository at this point in the history
Conflicts:
	test/test_transforms_v2_functional.py
	test/test_transforms_v2_refactored.py
  • Loading branch information
pmeier committed Aug 17, 2023
2 parents d94f316 + 4cba51c commit 37b1458
Show file tree
Hide file tree
Showing 26 changed files with 464 additions and 500 deletions.
3 changes: 1 addition & 2 deletions docs/source/transforms.rst
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,11 @@ Conversion

ToPILImage
v2.ToPILImage
v2.ToImagePIL
ToTensor
v2.ToTensor
PILToTensor
v2.PILToTensor
v2.ToImageTensor
v2.ToImage
ConvertImageDtype
v2.ConvertImageDtype
v2.ToDtype
Expand Down
4 changes: 2 additions & 2 deletions gallery/plot_transforms_v2_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def show(sample):

image, target = sample
if isinstance(image, PIL.Image.Image):
image = F.to_image_tensor(image)
image = F.to_image(image)
image = F.to_dtype(image, torch.uint8, scale=True)
annotated_image = draw_bounding_boxes(image, target["boxes"], colors="yellow", width=3)

Expand Down Expand Up @@ -101,7 +101,7 @@ def load_example_coco_detection_dataset(**kwargs):
transforms.RandomZoomOut(fill={PIL.Image.Image: (123, 117, 104), "others": 0}),
transforms.RandomIoUCrop(),
transforms.RandomHorizontalFlip(),
transforms.ToImageTensor(),
transforms.ToImage(),
transforms.ConvertImageDtype(torch.float32),
transforms.SanitizeBoundingBoxes(),
]
Expand Down
2 changes: 1 addition & 1 deletion packaging/pre_build_script.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if [[ "$(uname)" == Darwin ]]; then
conda install -yq wget
fi

if [[ "$(uname)" == Darwin || "$OSTYPE" == "msys" ]]; then
if [[ "$(uname)" == Darwin || "$OSTYPE" == "msys" || "$ARCH" == "aarch64" ]]; then
# Install libpng from Anaconda (defaults)
conda install libpng -yq
conda install -yq ffmpeg=4.2 libjpeg-turbo -c pytorch
Expand Down
8 changes: 4 additions & 4 deletions references/detection/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(
transforms = []
backend = backend.lower()
if backend == "datapoint":
transforms.append(T.ToImageTensor())
transforms.append(T.ToImage())
elif backend == "tensor":
transforms.append(T.PILToTensor())
elif backend != "pil":
Expand Down Expand Up @@ -71,7 +71,7 @@ def __init__(

if backend == "pil":
# Note: we could just convert to pure tensors even in v2.
transforms += [T.ToImageTensor() if use_v2 else T.PILToTensor()]
transforms += [T.ToImage() if use_v2 else T.PILToTensor()]

transforms += [T.ConvertImageDtype(torch.float)]

Expand All @@ -94,11 +94,11 @@ def __init__(self, backend="pil", use_v2=False):
backend = backend.lower()
if backend == "pil":
# Note: we could just convert to pure tensors even in v2?
transforms += [T.ToImageTensor() if use_v2 else T.PILToTensor()]
transforms += [T.ToImage() if use_v2 else T.PILToTensor()]
elif backend == "tensor":
transforms += [T.PILToTensor()]
elif backend == "datapoint":
transforms += [T.ToImageTensor()]
transforms += [T.ToImage()]
else:
raise ValueError(f"backend can be 'datapoint', 'tensor' or 'pil', but got {backend}")

Expand Down
6 changes: 3 additions & 3 deletions references/segmentation/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def __init__(
transforms = []
backend = backend.lower()
if backend == "datapoint":
transforms.append(T.ToImageTensor())
transforms.append(T.ToImage())
elif backend == "tensor":
transforms.append(T.PILToTensor())
elif backend != "pil":
Expand Down Expand Up @@ -81,7 +81,7 @@ def __init__(
if backend == "tensor":
transforms += [T.PILToTensor()]
elif backend == "datapoint":
transforms += [T.ToImageTensor()]
transforms += [T.ToImage()]
elif backend != "pil":
raise ValueError(f"backend can be 'datapoint', 'tensor' or 'pil', but got {backend}")

Expand All @@ -92,7 +92,7 @@ def __init__(

if backend == "pil":
# Note: we could just convert to pure tensors even in v2?
transforms += [T.ToImageTensor() if use_v2 else T.PILToTensor()]
transforms += [T.ToImage() if use_v2 else T.PILToTensor()]

transforms += [
T.ConvertImageDtype(torch.float),
Expand Down
10 changes: 5 additions & 5 deletions test/common_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from torch.testing._comparison import BooleanPair, NonePair, not_close_error_metas, NumberPair, TensorLikePair
from torchvision import datapoints, io
from torchvision.transforms._functional_tensor import _max_value as get_max_value
from torchvision.transforms.v2.functional import to_dtype_image_tensor, to_image_pil, to_image_tensor
from torchvision.transforms.v2.functional import to_dtype_image, to_image, to_pil_image


IN_OSS_CI = any(os.getenv(var) == "true" for var in ["CIRCLECI", "GITHUB_ACTIONS"])
Expand Down Expand Up @@ -294,7 +294,7 @@ def __init__(
**other_parameters,
):
if all(isinstance(input, PIL.Image.Image) for input in [actual, expected]):
actual, expected = [to_image_tensor(input) for input in [actual, expected]]
actual, expected = [to_image(input) for input in [actual, expected]]

super().__init__(actual, expected, **other_parameters)
self.mae = mae
Expand Down Expand Up @@ -547,7 +547,7 @@ def make_image_tensor(*args, **kwargs):


def make_image_pil(*args, **kwargs):
return to_image_pil(make_image(*args, **kwargs))
return to_pil_image(make_image(*args, **kwargs))


def make_image_loader(
Expand Down Expand Up @@ -620,12 +620,12 @@ def fn(shape, dtype, device, memory_format):
)
)

image_tensor = to_image_tensor(image_pil)
image_tensor = to_image(image_pil)
if memory_format == torch.contiguous_format:
image_tensor = image_tensor.to(device=device, memory_format=memory_format, copy=True)
else:
image_tensor = image_tensor.to(device=device)
image_tensor = to_dtype_image_tensor(image_tensor, dtype=dtype, scale=True)
image_tensor = to_dtype_image(image_tensor, dtype=dtype, scale=True)

return datapoints.Image(image_tensor)

Expand Down
4 changes: 2 additions & 2 deletions test/test_prototype_transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from torchvision.datapoints import BoundingBoxes, BoundingBoxFormat, Image, Mask, Video
from torchvision.prototype import datapoints, transforms
from torchvision.transforms.v2.functional import clamp_bounding_boxes, InterpolationMode, pil_to_tensor, to_image_pil
from torchvision.transforms.v2.functional import clamp_bounding_boxes, InterpolationMode, pil_to_tensor, to_pil_image
from torchvision.transforms.v2.utils import check_type, is_simple_tensor

BATCH_EXTRA_DIMS = [extra_dims for extra_dims in DEFAULT_EXTRA_DIMS if extra_dims]
Expand Down Expand Up @@ -387,7 +387,7 @@ def make_datapoints():
size = (600, 800)
num_objects = 22

pil_image = to_image_pil(make_image(size=size, color_space="RGB"))
pil_image = to_pil_image(make_image(size=size, color_space="RGB"))
target = {
"boxes": make_bounding_boxes(canvas_size=size, format="XYXY", batch_dims=(num_objects,), dtype=torch.float),
"labels": make_label(extra_dims=(num_objects,), categories=80),
Expand Down
29 changes: 6 additions & 23 deletions test/test_transforms_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -666,50 +666,33 @@ def test_check_transformed_types(self, inpt_type, mocker):
t(inpt)


class TestToImageTensor:
class TestToImage:
@pytest.mark.parametrize(
"inpt_type",
[torch.Tensor, PIL.Image.Image, datapoints.Image, np.ndarray, datapoints.BoundingBoxes, str, int],
)
def test__transform(self, inpt_type, mocker):
fn = mocker.patch(
"torchvision.transforms.v2.functional.to_image_tensor",
"torchvision.transforms.v2.functional.to_image",
return_value=torch.rand(1, 3, 8, 8),
)

inpt = mocker.MagicMock(spec=inpt_type)
transform = transforms.ToImageTensor()
transform = transforms.ToImage()
transform(inpt)
if inpt_type in (datapoints.BoundingBoxes, datapoints.Image, str, int):
assert fn.call_count == 0
else:
fn.assert_called_once_with(inpt)


class TestToImagePIL:
@pytest.mark.parametrize(
"inpt_type",
[torch.Tensor, PIL.Image.Image, datapoints.Image, np.ndarray, datapoints.BoundingBoxes, str, int],
)
def test__transform(self, inpt_type, mocker):
fn = mocker.patch("torchvision.transforms.v2.functional.to_image_pil")

inpt = mocker.MagicMock(spec=inpt_type)
transform = transforms.ToImagePIL()
transform(inpt)
if inpt_type in (datapoints.BoundingBoxes, PIL.Image.Image, str, int):
assert fn.call_count == 0
else:
fn.assert_called_once_with(inpt, mode=transform.mode)


class TestToPILImage:
@pytest.mark.parametrize(
"inpt_type",
[torch.Tensor, PIL.Image.Image, datapoints.Image, np.ndarray, datapoints.BoundingBoxes, str, int],
)
def test__transform(self, inpt_type, mocker):
fn = mocker.patch("torchvision.transforms.v2.functional.to_image_pil")
fn = mocker.patch("torchvision.transforms.v2.functional.to_pil_image")

inpt = mocker.MagicMock(spec=inpt_type)
transform = transforms.ToPILImage()
Expand Down Expand Up @@ -1013,7 +996,7 @@ def test_antialias_warning():
@pytest.mark.parametrize("image_type", (PIL.Image, torch.Tensor, datapoints.Image))
@pytest.mark.parametrize("label_type", (torch.Tensor, int))
@pytest.mark.parametrize("dataset_return_type", (dict, tuple))
@pytest.mark.parametrize("to_tensor", (transforms.ToTensor, transforms.ToImageTensor))
@pytest.mark.parametrize("to_tensor", (transforms.ToTensor, transforms.ToImage))
def test_classif_preset(image_type, label_type, dataset_return_type, to_tensor):

image = datapoints.Image(torch.randint(0, 256, size=(1, 3, 250, 250), dtype=torch.uint8))
Expand Down Expand Up @@ -1074,7 +1057,7 @@ def test_classif_preset(image_type, label_type, dataset_return_type, to_tensor):

@pytest.mark.parametrize("image_type", (PIL.Image, torch.Tensor, datapoints.Image))
@pytest.mark.parametrize("data_augmentation", ("hflip", "lsj", "multiscale", "ssd", "ssdlite"))
@pytest.mark.parametrize("to_tensor", (transforms.ToTensor, transforms.ToImageTensor))
@pytest.mark.parametrize("to_tensor", (transforms.ToTensor, transforms.ToImage))
@pytest.mark.parametrize("sanitize", (True, False))
def test_detection_preset(image_type, data_augmentation, to_tensor, sanitize):
torch.manual_seed(0)
Expand Down
16 changes: 8 additions & 8 deletions test/test_transforms_v2_consistency.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from torchvision.transforms import functional as legacy_F
from torchvision.transforms.v2 import functional as prototype_F
from torchvision.transforms.v2._utils import _get_fill
from torchvision.transforms.v2.functional import to_image_pil
from torchvision.transforms.v2.functional import to_pil_image
from torchvision.transforms.v2.utils import query_size

DEFAULT_MAKE_IMAGES_KWARGS = dict(color_spaces=["RGB"], extra_dims=[(4,)])
Expand Down Expand Up @@ -630,7 +630,7 @@ def check_call_consistency(
)

if image.ndim == 3 and supports_pil:
image_pil = to_image_pil(image)
image_pil = to_pil_image(image)

try:
torch.manual_seed(0)
Expand Down Expand Up @@ -869,7 +869,7 @@ def test_pil_to_tensor(self):
legacy_transform = legacy_transforms.PILToTensor()

for image in make_images(extra_dims=[()]):
image_pil = to_image_pil(image)
image_pil = to_pil_image(image)

assert_equal(prototype_transform(image_pil), legacy_transform(image_pil))

Expand All @@ -879,7 +879,7 @@ def test_to_tensor(self):
legacy_transform = legacy_transforms.ToTensor()

for image in make_images(extra_dims=[()]):
image_pil = to_image_pil(image)
image_pil = to_pil_image(image)
image_numpy = np.array(image_pil)

assert_equal(prototype_transform(image_pil), legacy_transform(image_pil))
Expand Down Expand Up @@ -1088,7 +1088,7 @@ def make_datapoints(self, with_mask=True):
def make_label(extra_dims, categories):
return torch.randint(categories, extra_dims, dtype=torch.int64)

pil_image = to_image_pil(make_image(size=size, color_space="RGB"))
pil_image = to_pil_image(make_image(size=size, color_space="RGB"))
target = {
"boxes": make_bounding_boxes(canvas_size=size, format="XYXY", batch_dims=(num_objects,), dtype=torch.float),
"labels": make_label(extra_dims=(num_objects,), categories=80),
Expand Down Expand Up @@ -1192,7 +1192,7 @@ def make_datapoints(self, supports_pil=True, image_dtype=torch.uint8):

conv_fns = []
if supports_pil:
conv_fns.append(to_image_pil)
conv_fns.append(to_pil_image)
conv_fns.extend([torch.Tensor, lambda x: x])

for conv_fn in conv_fns:
Expand All @@ -1201,8 +1201,8 @@ def make_datapoints(self, supports_pil=True, image_dtype=torch.uint8):

dp = (conv_fn(datapoint_image), datapoint_mask)
dp_ref = (
to_image_pil(datapoint_image) if supports_pil else datapoint_image.as_subclass(torch.Tensor),
to_image_pil(datapoint_mask),
to_pil_image(datapoint_image) if supports_pil else datapoint_image.as_subclass(torch.Tensor),
to_pil_image(datapoint_mask),
)

yield dp, dp_ref
Expand Down
26 changes: 13 additions & 13 deletions test/test_transforms_v2_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,12 @@ def test_float32_vs_uint8(self, test_id, info, args_kwargs):
adapted_other_args, adapted_kwargs = info.float32_vs_uint8(other_args, kwargs)

actual = info.kernel(
F.to_dtype_image_tensor(input, dtype=torch.float32, scale=True),
F.to_dtype_image(input, dtype=torch.float32, scale=True),
*adapted_other_args,
**adapted_kwargs,
)

expected = F.to_dtype_image_tensor(info.kernel(input, *other_args, **kwargs), dtype=torch.float32, scale=True)
expected = F.to_dtype_image(info.kernel(input, *other_args, **kwargs), dtype=torch.float32, scale=True)

assert_close(
actual,
Expand Down Expand Up @@ -377,7 +377,7 @@ def test_pil_output_type(self, info, args_kwargs):
if image_datapoint.ndim > 3:
pytest.skip("Input is batched")

image_pil = F.to_image_pil(image_datapoint)
image_pil = F.to_pil_image(image_datapoint)

output = info.dispatcher(image_pil, *other_args, **kwargs)

Expand Down Expand Up @@ -470,7 +470,7 @@ def test_bounding_boxes_format_consistency(self, info, args_kwargs):
(F.hflip, F.horizontal_flip),
(F.vflip, F.vertical_flip),
(F.get_image_num_channels, F.get_num_channels),
(F.to_pil_image, F.to_image_pil),
(F.to_pil_image, F.to_pil_image),
(F.elastic_transform, F.elastic),
(F.to_grayscale, F.rgb_to_grayscale),
]
Expand All @@ -493,7 +493,7 @@ def assert_samples_from_standard_normal(t):
mean = image.mean(dim=(1, 2)).tolist()
std = image.std(dim=(1, 2)).tolist()

assert_samples_from_standard_normal(F.normalize_image_tensor(image, mean, std))
assert_samples_from_standard_normal(F.normalize_image(image, mean, std))


class TestClampBoundingBoxes:
Expand Down Expand Up @@ -864,7 +864,7 @@ def _compute_expected_mask(mask, output_size):
_, image_height, image_width = mask.shape
if crop_width > image_height or crop_height > image_width:
padding = _center_crop_compute_padding(crop_height, crop_width, image_height, image_width)
mask = F.pad_image_tensor(mask, padding, fill=0)
mask = F.pad_image(mask, padding, fill=0)

left = round((image_width - crop_width) * 0.5)
top = round((image_height - crop_height) * 0.5)
Expand All @@ -885,7 +885,7 @@ def _compute_expected_mask(mask, output_size):
@pytest.mark.parametrize("ksize", [(3, 3), [3, 5], (23, 23)])
@pytest.mark.parametrize("sigma", [[0.5, 0.5], (0.5, 0.5), (0.8, 0.8), (1.7, 1.7)])
def test_correctness_gaussian_blur_image_tensor(device, canvas_size, dt, ksize, sigma):
fn = F.gaussian_blur_image_tensor
fn = F.gaussian_blur_image

# true_cv2_results = {
# # np_img = np.arange(3 * 10 * 12, dtype="uint8").reshape((10, 12, 3))
Expand Down Expand Up @@ -942,8 +942,8 @@ def test_correctness_gaussian_blur_image_tensor(device, canvas_size, dt, ksize,
PIL.Image.new("RGB", (32, 32), 122),
],
)
def test_to_image_tensor(inpt):
output = F.to_image_tensor(inpt)
def test_to_image(inpt):
output = F.to_image(inpt)
assert isinstance(output, torch.Tensor)
assert output.shape == (3, 32, 32)

Expand All @@ -958,21 +958,21 @@ def test_to_image_tensor(inpt):
],
)
@pytest.mark.parametrize("mode", [None, "RGB"])
def test_to_image_pil(inpt, mode):
output = F.to_image_pil(inpt, mode=mode)
def test_to_pil_image(inpt, mode):
output = F.to_pil_image(inpt, mode=mode)
assert isinstance(output, PIL.Image.Image)

assert np.asarray(inpt).sum() == np.asarray(output).sum()


def test_equalize_image_tensor_edge_cases():
inpt = torch.zeros(3, 200, 200, dtype=torch.uint8)
output = F.equalize_image_tensor(inpt)
output = F.equalize_image(inpt)
torch.testing.assert_close(inpt, output)

inpt = torch.zeros(5, 3, 200, 200, dtype=torch.uint8)
inpt[..., 100:, 100:] = 1
output = F.equalize_image_tensor(inpt)
output = F.equalize_image(inpt)
assert output.unique().tolist() == [0, 255]


Expand Down
Loading

0 comments on commit 37b1458

Please sign in to comment.