Files
wehub-resource-sync 3a2c66702c
Tests on CPU (scheduled) / check-skip (push) Has been cancelled
Tests on CPU (scheduled) / pre-tests (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-ubuntu (float32) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-ubuntu (float64) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float64, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.11, float64, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float64, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.12, float64, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.13, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-windows (3.13, float64, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.11, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.11, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.12, float32, 2.5.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.12, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / tests-cpu-mac (3.13, float32, 2.9.1) (push) Has been cancelled
Tests on CPU (scheduled) / coverage (push) Has been cancelled
Tests on CPU (scheduled) / typing (push) Has been cancelled
Tests on CPU (scheduled) / tutorials (push) Has been cancelled
Tests on CPU (scheduled) / docs (push) Has been cancelled
Lint / TOML Format (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:49:27 +08:00

1557 lines
63 KiB
Python

# LICENSE HEADER MANAGED BY add-license-header
#
# Copyright 2018 Kornia Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import pytest
import torch
from torch import Tensor
from kornia.augmentation.random_generator import (
AffineGenerator,
ColorJiggleGenerator,
ColorJitterGenerator,
CropGenerator,
CutmixGenerator,
MixupGenerator,
MotionBlurGenerator,
PerspectiveGenerator,
PlainUniformGenerator,
PosterizeGenerator,
ProbabilityGenerator,
RectangleEraseGenerator,
ResizedCropGenerator,
center_crop_generator,
)
from kornia.core._compat import torch_version_ge
from testing.base import assert_close
class RandomGeneratorBaseTests:
def test_valid_param_combinations(self, device, dtype):
raise NotImplementedError
def test_invalid_param_combinations(self, device, dtype):
raise NotImplementedError
def test_random_gen(self, device, dtype):
raise NotImplementedError
def test_same_on_batch(self, device, dtype):
raise NotImplementedError
class TestRandomProbGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("p", [0.0, 0.5, 1.0])
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, p, batch_size, same_on_batch):
ProbabilityGenerator(p)(torch.Size([batch_size]), same_on_batch)
@pytest.mark.parametrize(
"p",
[
# Should be failed if p > 1. or p < 0.
(-1.0),
(2.0),
],
)
def test_invalid_param_combinations(self, p):
with pytest.raises(Exception):
ProbabilityGenerator(p)(torch.Size([8]))
@pytest.mark.parametrize(
"p,expected",
[
(0.0, [False] * 8),
(0.5, [False, False, True, False, True, False, True, False]),
(1.0, [True] * 8),
],
)
def test_random_gen(self, p, expected, device, dtype):
torch.manual_seed(42)
batch_size = 8
res = ProbabilityGenerator(p)(torch.Size([batch_size]))
assert (res["probs"] == torch.tensor(expected)).long().sum() == batch_size
@pytest.mark.parametrize("seed,expected", [(42, [False] * 8), (0, [True] * 8)])
def test_same_on_batch(self, seed, expected, device, dtype):
torch.manual_seed(seed)
batch_size = 8
res = ProbabilityGenerator(0.5)(torch.Size([batch_size]), True)
assert (res["probs"] == torch.tensor(expected)).long().sum() == batch_size
class TestColorJiggleGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("brightness", [None, torch.tensor([0.8, 1.2])])
@pytest.mark.parametrize("contrast", [None, torch.tensor([0.8, 1.2])])
@pytest.mark.parametrize("saturation", [None, torch.tensor([0.8, 1.2])])
@pytest.mark.parametrize("hue", [None, torch.tensor([-0.1, 0.1])])
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(
self,
brightness,
contrast,
saturation,
hue,
batch_size,
same_on_batch,
device,
dtype,
):
ColorJiggleGenerator(
torch.as_tensor(
brightness if brightness is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
contrast if contrast is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
saturation if saturation is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
hue if hue is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
)(torch.Size([batch_size]), same_on_batch)
@pytest.mark.parametrize(
"brightness,contrast,saturation,hue",
[
# Should be failed if value out of bounds or tensor.shape != [1, 2]
(torch.tensor([-1.0, 2.0]), None, None, None),
(torch.tensor([0.0, 3.0]), None, None, None),
(torch.tensor([0.0]), None, None, None),
(torch.tensor([0.0, 1.0, 2.0]), None, None, None),
(None, torch.tensor([-1.0, 2.0]), None, None),
(None, torch.tensor([0.0]), None, None),
(None, torch.tensor([0.0, 1.0, 2.0]), None, None),
(None, None, torch.tensor([-1.0, 2.0]), None),
(None, None, torch.tensor([0.0]), None),
(None, None, torch.tensor([0.0, 1.0, 2.0]), None),
(None, None, None, torch.tensor([-1.0, 0.0])),
(None, None, None, torch.tensor([0, 1.0])),
(None, None, None, torch.tensor([0.0])),
(None, None, None, torch.tensor([0.0, 1.0, 2.0])),
],
)
def test_invalid_param_combinations(self, brightness, contrast, saturation, hue, device, dtype):
with pytest.raises(Exception):
ColorJiggleGenerator(
torch.as_tensor(
brightness if brightness is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
contrast if contrast is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
saturation if saturation is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
hue if hue is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
)(torch.Size([8]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
batch_size = 8
jitter_params = ColorJiggleGenerator(
brightness=torch.tensor([0.8, 1.2], device=device, dtype=dtype),
contrast=torch.tensor([0.7, 1.3], device=device, dtype=dtype),
saturation=torch.tensor([0.6, 1.4], device=device, dtype=dtype),
hue=torch.tensor([-0.1, 0.1], device=device, dtype=dtype),
)(torch.Size([batch_size]))
expected_jitter_params = {
"brightness_factor": torch.tensor(
[1.1529, 1.1660, 0.9531, 1.1837, 0.9562, 1.0404, 0.9026, 1.1175],
device=device,
dtype=dtype,
),
"contrast_factor": torch.tensor(
[1.2645, 0.7799, 1.2608, 1.0561, 1.2216, 1.0406, 1.1447, 0.9576],
device=device,
dtype=dtype,
),
"hue_factor": torch.tensor(
[0.0771, 0.0148, -0.0467, 0.0255, -0.0461, -0.0117, -0.0406, 0.0663],
device=device,
dtype=dtype,
),
"saturation_factor": torch.tensor(
[0.6843, 0.8156, 0.8871, 0.7595, 1.0378, 0.6049, 1.3612, 0.6602],
device=device,
dtype=dtype,
),
"order": torch.tensor([3, 2, 0, 1], device=device, dtype=torch.long),
}
assert set(jitter_params.keys()) == {
"brightness_factor",
"contrast_factor",
"hue_factor",
"saturation_factor",
"order",
}, (
"Redundant keys found apart from \
'brightness_factor', 'contrast_factor', 'hue_factor', 'saturation_factor', 'order'"
)
assert_close(
jitter_params["brightness_factor"],
expected_jitter_params["brightness_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["contrast_factor"],
expected_jitter_params["contrast_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["hue_factor"],
expected_jitter_params["hue_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["saturation_factor"],
expected_jitter_params["saturation_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["order"],
expected_jitter_params["order"],
rtol=1e-4,
atol=1e-4,
)
def test_random_gen_accumulative_additive_additive(self, device, dtype):
torch.manual_seed(42)
batch_size = 8
jitter_params = ColorJiggleGenerator(
brightness=torch.tensor([0.8, 1.2], device=device, dtype=dtype),
contrast=torch.tensor([0.7, 1.3], device=device, dtype=dtype),
saturation=torch.tensor([0.6, 1.4], device=device, dtype=dtype),
hue=torch.tensor([-0.1, 0.1], device=device, dtype=dtype),
)(torch.Size([batch_size]))
expected_jitter_params = {
"brightness_factor": torch.tensor(
[1.1529, 1.1660, 0.9531, 1.1837, 0.9562, 1.0404, 0.9026, 1.1175],
device=device,
dtype=dtype,
),
"contrast_factor": torch.tensor(
[1.2645, 0.7799, 1.2608, 1.0561, 1.2216, 1.0406, 1.1447, 0.9576],
device=device,
dtype=dtype,
),
"hue_factor": torch.tensor(
[0.0771, 0.0148, -0.0467, 0.0255, -0.0461, -0.0117, -0.0406, 0.0663],
device=device,
dtype=dtype,
),
"saturation_factor": torch.tensor(
[0.6843, 0.8156, 0.8871, 0.7595, 1.0378, 0.6049, 1.3612, 0.6602],
device=device,
dtype=dtype,
),
"order": torch.tensor([3, 2, 0, 1], device=device, dtype=torch.long),
}
assert set(jitter_params.keys()) == {
"brightness_factor",
"contrast_factor",
"hue_factor",
"saturation_factor",
"order",
}, (
"Redundant keys found apart from \
'brightness_factor', 'contrast_factor', 'hue_factor', 'saturation_factor', 'order'"
)
assert_close(
jitter_params["brightness_factor"],
expected_jitter_params["brightness_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["contrast_factor"],
expected_jitter_params["contrast_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["hue_factor"],
expected_jitter_params["hue_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["saturation_factor"],
expected_jitter_params["saturation_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["order"],
expected_jitter_params["order"],
rtol=1e-4,
atol=1e-4,
)
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
batch_size = 8
jitter_params = ColorJiggleGenerator(
brightness=torch.tensor([0.8, 1.2], device=device, dtype=dtype),
contrast=torch.tensor([0.7, 1.3], device=device, dtype=dtype),
saturation=torch.tensor([0.6, 1.4], device=device, dtype=dtype),
hue=torch.tensor([-0.1, 0.1], device=device, dtype=dtype),
)(torch.Size([batch_size]), same_on_batch=True)
expected_res = {
"brightness_factor": torch.tensor([1.1529] * batch_size, device=device, dtype=dtype),
"contrast_factor": torch.tensor([1.2490] * batch_size, device=device, dtype=dtype),
"hue_factor": torch.tensor([-0.0234] * batch_size, device=device, dtype=dtype),
"saturation_factor": torch.tensor([1.3674] * batch_size, device=device, dtype=dtype),
"order": torch.tensor([2, 3, 0, 1], device=device, dtype=torch.long),
}
assert_close(
jitter_params["brightness_factor"],
expected_res["brightness_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["contrast_factor"],
expected_res["contrast_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["hue_factor"],
expected_res["hue_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["saturation_factor"],
expected_res["saturation_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["order"],
expected_res["order"],
rtol=1e-4,
atol=1e-4,
)
class TestColorJitterGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("brightness", [None, torch.tensor([0.8, 1.2])])
@pytest.mark.parametrize("contrast", [None, torch.tensor([0.8, 1.2])])
@pytest.mark.parametrize("saturation", [None, torch.tensor([0.8, 1.2])])
@pytest.mark.parametrize("hue", [None, torch.tensor([-0.1, 0.1])])
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(
self,
brightness,
contrast,
saturation,
hue,
batch_size,
same_on_batch,
device,
dtype,
):
ColorJitterGenerator(
torch.as_tensor(
brightness if brightness is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
contrast if contrast is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
saturation if saturation is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
hue if hue is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
)(torch.Size([batch_size]), same_on_batch)
@pytest.mark.parametrize(
"brightness,contrast,saturation,hue",
[
# Should be failed if value out of bounds or tensor.shape != [1, 2]
(torch.tensor([-1.0, 2.0]), None, None, None),
(torch.tensor([0.0]), None, None, None),
(torch.tensor([0.0, 1.0, 2.0]), None, None, None),
(None, torch.tensor([-1.0, 2.0]), None, None),
(None, torch.tensor([0.0]), None, None),
(None, torch.tensor([0.0, 1.0, 2.0]), None, None),
(None, None, torch.tensor([-1.0, 2.0]), None),
(None, None, torch.tensor([0.0]), None),
(None, None, torch.tensor([0.0, 1.0, 2.0]), None),
(None, None, None, torch.tensor([-1.0, 0.0])),
(None, None, None, torch.tensor([0, 1.0])),
(None, None, None, torch.tensor([0.0])),
(None, None, None, torch.tensor([0.0, 1.0, 2.0])),
],
)
def test_invalid_param_combinations(self, brightness, contrast, saturation, hue, device, dtype):
with pytest.raises(Exception):
ColorJitterGenerator(
torch.as_tensor(
brightness if brightness is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
contrast if contrast is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
saturation if saturation is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
torch.as_tensor(
hue if hue is not None else torch.tensor([0.0, 0.0]),
device=device,
dtype=dtype,
),
)(torch.Size([8]))
def test_random_gen(self, device, dtype):
# TODO(jian): crashes with pytorch 1.10, cuda and fp64
if (torch_version_ge(1, 10) and "cuda" in str(device)) or dtype == torch.float64:
pytest.skip("AssertionError: cannot reproduce the same result")
torch.manual_seed(42)
batch_size = 8
gen = ColorJitterGenerator(
brightness=torch.tensor([0.8, 1.2], device=device, dtype=dtype),
contrast=torch.tensor([0.7, 1.3], device=device, dtype=dtype),
saturation=torch.tensor([0.6, 1.4], device=device, dtype=dtype),
hue=torch.tensor([-0.1, 0.1], device=device, dtype=dtype),
).to(device, dtype)
jitter_params = gen(torch.Size([batch_size]))
expected_jitter_params = {
"brightness_factor": torch.tensor(
[1.1529, 1.1660, 0.9531, 1.1837, 0.9562, 1.0404, 0.9026, 1.1175],
device=device,
dtype=dtype,
),
"contrast_factor": torch.tensor(
[1.2645, 0.7799, 1.2608, 1.0561, 1.2216, 1.0406, 1.1447, 0.9576],
device=device,
dtype=dtype,
),
"hue_factor": torch.tensor(
[0.0771, 0.0148, -0.0467, 0.0255, -0.0461, -0.0117, -0.0406, 0.0663],
device=device,
dtype=dtype,
),
"saturation_factor": torch.tensor(
[0.6843, 0.8156, 0.8871, 0.7595, 1.0378, 0.6049, 1.3612, 0.6602],
device=device,
dtype=dtype,
),
"order": torch.tensor([3, 2, 0, 1], device=device, dtype=torch.long),
}
assert set(jitter_params.keys()) == {
"brightness_factor",
"contrast_factor",
"hue_factor",
"saturation_factor",
"order",
}, (
"Redundant keys found apart from \
'brightness_factor', 'contrast_factor', 'hue_factor', 'saturation_factor', 'order'"
)
assert_close(
jitter_params["brightness_factor"],
expected_jitter_params["brightness_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["contrast_factor"],
expected_jitter_params["contrast_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["hue_factor"],
expected_jitter_params["hue_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["saturation_factor"],
expected_jitter_params["saturation_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["order"],
expected_jitter_params["order"],
rtol=1e-4,
atol=1e-4,
)
def test_same_on_batch(self, device, dtype):
if "cuda" in str(device) or dtype == torch.float64:
pytest.skip("AssertionError: cannot reproduce the same result")
torch.manual_seed(42)
batch_size = 8
gen = ColorJitterGenerator(
brightness=torch.tensor([0.8, 1.2], device=device, dtype=dtype),
contrast=torch.tensor([0.7, 1.3], device=device, dtype=dtype),
saturation=torch.tensor([0.6, 1.4], device=device, dtype=dtype),
hue=torch.tensor([-0.1, 0.1], device=device, dtype=dtype),
).to(device, dtype)
jitter_params = gen(torch.Size([batch_size]), same_on_batch=True)
expected_res = {
"brightness_factor": torch.tensor([1.1529] * batch_size, device=device, dtype=dtype),
"contrast_factor": torch.tensor([1.2490] * batch_size, device=device, dtype=dtype),
"hue_factor": torch.tensor([-0.0234] * batch_size, device=device, dtype=dtype),
"saturation_factor": torch.tensor([1.3674] * batch_size, device=device, dtype=dtype),
"order": torch.tensor([2, 3, 0, 1], device=device, dtype=torch.long),
}
assert_close(
jitter_params["brightness_factor"],
expected_res["brightness_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["contrast_factor"],
expected_res["contrast_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["hue_factor"],
expected_res["hue_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["saturation_factor"],
expected_res["saturation_factor"],
rtol=1e-4,
atol=1e-4,
)
assert_close(
jitter_params["order"],
expected_res["order"],
rtol=1e-4,
atol=1e-4,
)
class TestRandomPerspectiveGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("height,width", [(200, 200)])
@pytest.mark.parametrize("distortion_scale", [torch.tensor(0.0), torch.tensor(0.5), torch.tensor(1.0)])
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, height, width, distortion_scale, batch_size, same_on_batch, device, dtype):
PerspectiveGenerator(distortion_scale.to(device=device, dtype=dtype))(
torch.Size([batch_size, 1, height, width]), same_on_batch
)
@pytest.mark.parametrize(
"height,width,distortion_scale",
[
# Should be failed if distortion_scale > 1. or distortion_scale < 0.
(-100, 100, torch.tensor(0.5)),
(100, -100, torch.tensor(0.5)),
(100, 100, torch.tensor(-0.5)),
(100, 100, torch.tensor(1.5)),
(100, 100, torch.tensor([0.0, 0.5])),
],
)
def test_invalid_param_combinations(self, height, width, distortion_scale, device, dtype):
with pytest.raises(Exception):
PerspectiveGenerator(distortion_scale.to(device=device, dtype=dtype))(torch.Size([8, 1, height, width]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
batch_size = 2
res = PerspectiveGenerator(torch.tensor(0.5, device=device, dtype=dtype))(torch.Size([batch_size, 1, 200, 200]))
expected = {
"start_points": torch.tensor(
[
[[0.0, 0.0], [199.0, 0.0], [199.0, 199.0], [0.0, 199.0]],
[[0.0, 0.0], [199.0, 0.0], [199.0, 199.0], [0.0, 199.0]],
],
device=device,
dtype=dtype,
),
"end_points": torch.tensor(
[
[
[44.1135, 45.7502],
[179.8568, 47.9653],
[179.4776, 168.9552],
[12.8286, 159.3179],
],
[
[47.0386, 6.6593],
[152.2701, 29.6790],
[155.5298, 170.6142],
[37.0547, 177.5298],
],
],
device=device,
dtype=dtype,
),
}
assert res.keys() == expected.keys()
assert_close(res["start_points"], expected["start_points"])
assert_close(res["end_points"], expected["end_points"])
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
batch_size = 2
res = PerspectiveGenerator(torch.tensor(0.5, device=device, dtype=dtype))(
torch.Size([batch_size, 1, 200, 200]), same_on_batch=True
)
expected = {
"start_points": torch.tensor(
[[[0.0, 0.0], [199.0, 0.0], [199.0, 199.0], [0.0, 199.0]]],
device=device,
dtype=dtype,
).repeat(2, 1, 1),
"end_points": torch.tensor(
[
[
[44.1135, 45.7502],
[179.8568, 47.9653],
[179.4776, 168.9552],
[12.8286, 159.3179],
]
],
device=device,
dtype=dtype,
).repeat(2, 1, 1),
}
assert res.keys() == expected.keys()
assert_close(res["start_points"], expected["start_points"])
assert_close(res["end_points"], expected["end_points"])
def test_sampling_method(self, device, dtype):
torch.manual_seed(42)
batch_size = 2
res = PerspectiveGenerator(
torch.tensor(0.5, device=device, dtype=dtype),
sampling_method="area_preserving",
)(torch.Size([batch_size, 1, 200, 200]))
expected = {
"start_points": torch.tensor(
[
[[0.0, 0.0], [199.0, 0.0], [199.0, 199.0], [0.0, 199.0]],
[[0.0, 0.0], [199.0, 0.0], [199.0, 199.0], [0.0, 199.0]],
],
device=device,
dtype=dtype,
),
"end_points": torch.tensor(
[
[
[38.2269, 41.5004],
[187.2864, 45.9306],
[188.0448, 209.0895],
[-24.3428, 228.3641],
],
[
[44.0771, -36.6814],
[242.4598, 9.3580],
[235.9404, 205.7715],
[24.1094, 191.9404],
],
],
device=device,
dtype=dtype,
),
}
assert res.keys() == expected.keys()
assert_close(res["start_points"], expected["start_points"])
assert_close(res["end_points"], expected["end_points"])
def test_not_implemented_sampling_method(self, device, dtype):
batch_size = 2
with pytest.raises(NotImplementedError):
PerspectiveGenerator(
torch.tensor(0.5, device=device, dtype=dtype),
sampling_method="non_existing_method",
)(torch.Size([batch_size, 1, 200, 200]))
class TestRandomAffineGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 4])
@pytest.mark.parametrize("height", [200])
@pytest.mark.parametrize("width", [300])
@pytest.mark.parametrize("degrees", [torch.tensor([0, 30])])
@pytest.mark.parametrize("translate", [None, torch.tensor([0.1, 0.1])])
@pytest.mark.parametrize("scale", [None, torch.tensor([0.7, 1.2])])
@pytest.mark.parametrize("shear", [None, torch.tensor([[0, 20], [0, 20]])])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(
self,
batch_size,
height,
width,
degrees,
translate,
scale,
shear,
same_on_batch,
device,
dtype,
):
AffineGenerator(
degrees=degrees.to(device=device, dtype=dtype),
translate=(translate.to(device=device, dtype=dtype) if translate is not None else None),
scale=scale.to(device=device, dtype=dtype) if scale is not None else None,
shear=shear.to(device=device, dtype=dtype) if shear is not None else None,
)(torch.Size([batch_size, 1, height, width]), same_on_batch)
@pytest.mark.parametrize(
"height,width,degrees,translate,scale,shear",
[
(-100, 100, torch.tensor([10, 20]), None, None, None),
(100, -100, torch.tensor([10, 20]), None, None, None),
(100, 100, 0.5, None, None, None),
(100, 100, torch.tensor([10, 20, 30]), None, None, None),
(100, 100, torch.tensor([10, 20]), torch.tensor([0.1]), None, None),
(10, 10, torch.tensor([1, 2]), torch.tensor([0.1, 0.2, 0.3]), None, None),
(100, 100, torch.tensor([10, 20]), None, torch.tensor([1]), None),
(100, 100, torch.tensor([10, 20]), None, torch.tensor([1, 2, 3]), None),
(100, 100, torch.tensor([10, 20]), None, None, torch.tensor([1])),
(10, 10, torch.tensor([1, 2]), None, None, torch.tensor([1, 2, 3])),
(10, 10, torch.tensor([1, 2]), None, None, torch.tensor([1, 2, 3, 4, 5])),
],
)
def test_invalid_param_combinations(self, height, width, degrees, translate, scale, shear, device, dtype):
with pytest.raises(Exception):
AffineGenerator(
degrees=degrees.to(device=device, dtype=dtype),
translate=(translate.to(device=device, dtype=dtype) if translate is not None else None),
scale=(scale.to(device=device, dtype=dtype) if scale is not None else None),
shear=(shear.to(device=device, dtype=dtype) if shear is not None else None),
)(torch.Size([8, 1, height, width]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
degrees = torch.tensor([10, 20], device=device, dtype=dtype)
translate = torch.tensor([0.1, 0.1], device=device, dtype=dtype)
scale = torch.tensor([0.7, 1.2], device=device, dtype=dtype)
shear = torch.tensor([[10, 20], [10, 20]], device=device, dtype=dtype)
res = AffineGenerator(
degrees=degrees.to(device=device, dtype=dtype),
translate=(translate.to(device=device, dtype=dtype) if translate is not None else None),
scale=scale.to(device=device, dtype=dtype) if scale is not None else None,
shear=shear.to(device=device, dtype=dtype) if shear is not None else None,
)(torch.Size([2, 1, 200, 200]))
expected = {
"translations": torch.tensor([[-4.3821, -9.7371], [4.0358, 11.7457]], device=device, dtype=dtype),
"center": torch.tensor([[99.5000, 99.5000], [99.5000, 99.5000]], device=device, dtype=dtype),
"scale": torch.tensor([[0.8914, 0.8914], [1.1797, 1.1797]], device=device, dtype=dtype),
"angle": torch.tensor([18.8227, 19.1500], device=device, dtype=dtype),
"shear_x": torch.tensor([19.4077, 11.3319], device=device, dtype=dtype),
"shear_y": torch.tensor([19.3460, 15.9358], device=device, dtype=dtype),
}
assert res.keys() == expected.keys()
assert_close(res["translations"], expected["translations"], rtol=1e-4, atol=1e-4)
assert_close(res["center"], expected["center"], rtol=1e-4, atol=1e-4)
assert_close(res["scale"], expected["scale"], rtol=1e-4, atol=1e-4)
assert_close(res["angle"], expected["angle"], rtol=1e-4, atol=1e-4)
assert_close(res["shear_x"], expected["shear_x"], rtol=1e-4, atol=1e-4)
assert_close(res["shear_y"], expected["shear_y"], rtol=1e-4, atol=1e-4)
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
degrees = torch.tensor([10, 20], device=device, dtype=dtype)
translate = torch.tensor([0.1, 0.1], device=device, dtype=dtype)
scale = torch.tensor([0.7, 1.2], device=device, dtype=dtype)
shear = torch.tensor([[10, 20], [10, 20]], device=device, dtype=dtype)
res = AffineGenerator(
degrees=degrees.to(device=device, dtype=dtype),
translate=(translate.to(device=device, dtype=dtype) if translate is not None else None),
scale=scale.to(device=device, dtype=dtype) if scale is not None else None,
shear=shear.to(device=device, dtype=dtype) if shear is not None else None,
)(torch.Size([2, 1, 200, 200]), True)
expected = {
"translations": torch.tensor([[-4.6854, 18.3722], [-4.6854, 18.3722]], device=device, dtype=dtype),
"center": torch.tensor([[99.5000, 99.5000], [99.5000, 99.5000]], device=device, dtype=dtype),
"scale": torch.tensor([[1.1575, 1.1575], [1.1575, 1.1575]], device=device, dtype=dtype),
"angle": torch.tensor([18.8227, 18.8227], device=device, dtype=dtype),
"shear_x": torch.tensor([13.9045, 13.9045], device=device, dtype=dtype),
"shear_y": torch.tensor([16.0090, 16.0090], device=device, dtype=dtype),
}
assert res.keys() == expected.keys()
assert_close(res["translations"], expected["translations"], rtol=1e-4, atol=1e-4)
assert_close(res["center"], expected["center"], rtol=1e-4, atol=1e-4)
assert_close(res["scale"], expected["scale"], rtol=1e-4, atol=1e-4)
assert_close(res["angle"], expected["angle"], rtol=1e-4, atol=1e-4)
assert_close(res["shear_x"], expected["shear_x"], rtol=1e-4, atol=1e-4)
assert_close(res["shear_y"], expected["shear_y"], rtol=1e-4, atol=1e-4)
class TestRandomCropGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 2])
@pytest.mark.parametrize("input_size", [(200, 200)])
@pytest.mark.parametrize("size", [(100, 100), torch.tensor([50, 50])])
@pytest.mark.parametrize("resize_to", [None, (100, 100)])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, batch_size, input_size, size, resize_to, same_on_batch, device, dtype):
if isinstance(size, Tensor):
size = size.repeat(batch_size, 1).to(device=device, dtype=dtype)
CropGenerator(size, resize_to)(torch.Size([batch_size, 1, *input_size]), same_on_batch)
@pytest.mark.parametrize(
"input_size,size,resize_to",
[
((-300, 300), (200, 200), (100, 100)),
((200, 200), torch.tensor([50, 50]), (100, 100)),
],
)
def test_invalid_param_combinations(self, input_size, size, resize_to, device, dtype):
batch_size = 2
with pytest.raises(Exception):
CropGenerator(
(size.to(device=device, dtype=dtype) if isinstance(size, Tensor) else size),
resize_to,
)(torch.Size([batch_size, 1, *input_size]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
res = CropGenerator(torch.tensor([[50, 60], [70, 80]], device=device, dtype=dtype), (200, 200))(
torch.Size([2, 1, 100, 100])
)
expected = {
"src": torch.tensor(
[
[[36, 19], [95, 19], [95, 68], [36, 68]],
[[19, 29], [98, 29], [98, 98], [19, 98]],
],
device=device,
dtype=dtype,
),
"dst": torch.tensor(
[
[[0, 0], [199, 0], [199, 199], [0, 199]],
[[0, 0], [199, 0], [199, 199], [0, 199]],
],
device=device,
dtype=dtype,
),
"input_size": torch.tensor([[100, 100], [100, 100]], device=device, dtype=torch.long),
"output_size": torch.tensor([[200, 200], [200, 200]], device=device, dtype=torch.long),
}
assert res.keys() == expected.keys()
assert_close(res["src"], expected["src"])
assert_close(res["dst"], expected["dst"])
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
res = CropGenerator(torch.tensor([[50, 60], [70, 80]], device=device, dtype=dtype), (200, 200))(
torch.Size([2, 1, 100, 100]), True
)
expected = {
"src": torch.tensor(
[
[[36, 46], [95, 46], [95, 95], [36, 95]],
[[36, 46], [115, 46], [115, 115], [36, 115]],
],
device=device,
dtype=dtype,
),
"dst": torch.tensor(
[
[[0, 0], [199, 0], [199, 199], [0, 199]],
[[0, 0], [199, 0], [199, 199], [0, 199]],
],
device=device,
dtype=dtype,
),
"input_size": torch.tensor([[100, 100], [100, 100]], device=device, dtype=torch.long),
"output_size": torch.tensor([[200, 200], [200, 200]], device=device, dtype=torch.long),
}
assert res.keys() == expected.keys()
assert_close(res["src"], expected["src"])
assert_close(res["dst"], expected["dst"])
class TestRandomCropSizeGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("size", [(200, 200)])
@pytest.mark.parametrize("scale", [torch.tensor([0.7, 1.3])])
@pytest.mark.parametrize("ratio", [torch.tensor([0.9, 1.1])])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, batch_size, size, scale, ratio, same_on_batch, device, dtype):
ResizedCropGenerator(
size,
torch.as_tensor(scale, device=device, dtype=dtype),
torch.as_tensor(ratio, device=device, dtype=dtype),
)(torch.Size([batch_size, 1, 300, 300]), same_on_batch)
@pytest.mark.parametrize(
"size,scale,ratio",
[
((100), torch.tensor([0.7, 1.3]), torch.tensor([0.9, 1.1])),
((100, 100, 100), torch.tensor([0.7, 1.3]), torch.tensor([0.9, 1.1])),
((100, 100), torch.tensor([0.7]), torch.tensor([0.9, 1.1])),
((100, 100), torch.tensor([0.7, 1.3, 1.5]), torch.tensor([0.9, 1.1])),
((100, 100), torch.tensor([0.7, 1.3]), torch.tensor([0.9])),
((100, 100), torch.tensor([0.7, 1.3]), torch.tensor([0.9, 1.1, 1.3])),
],
)
def test_invalid_param_combinations(self, size, scale, ratio, device, dtype):
batch_size = 2
with pytest.raises(Exception):
ResizedCropGenerator(
size,
torch.as_tensor(scale, device=device, dtype=dtype),
torch.as_tensor(ratio, device=device, dtype=dtype),
)(torch.Size([batch_size, 1, 300, 300]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
res = ResizedCropGenerator(
(100, 100),
torch.tensor([0.7, 1.3], device=device, dtype=dtype),
torch.tensor([0.9, 1.1], device=device, dtype=dtype),
)(torch.Size([2, 1, 300, 300]))
expected = {
"src": torch.tensor(
[
[[11.0, 3.0], [293.0, 3.0], [293.0, 298.0], [11.0, 298.0]],
[[8.0, 22.0], [286.0, 22.0], [286.0, 298.0], [8.0, 298.0]],
],
device=device,
dtype=dtype,
),
"dst": torch.tensor(
[
[[0.0, 0.0], [99.0, 0.0], [99.0, 99.0], [0.0, 99.0]],
[[0.0, 0.0], [99.0, 0.0], [99.0, 99.0], [0.0, 99.0]],
],
device=device,
dtype=dtype,
),
"input_size": torch.tensor([[300, 300], [300, 300]], device=device, dtype=torch.int64),
"output_size": torch.tensor([[100, 100], [100, 100]], device=device, dtype=torch.long),
}
assert res.keys() == expected.keys()
assert_close(res["src"], expected["src"])
assert_close(res["dst"], expected["dst"])
assert_close(res["input_size"], expected["input_size"])
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
res = ResizedCropGenerator(
(100, 100),
torch.tensor([0.7, 1.3], device=device, dtype=dtype),
torch.tensor([0.9, 1.1], device=device, dtype=dtype),
)(torch.Size([2, 1, 300, 300]), same_on_batch=True)
expected = {
"src": torch.tensor(
[
[[0.0, 9.0], [298.0, 9.0], [298.0, 287.0], [0.0, 287.0]],
[[0.0, 9.0], [298.0, 9.0], [298.0, 287.0], [0.0, 287.0]],
],
device=device,
dtype=dtype,
),
"dst": torch.tensor(
[
[[0.0, 0.0], [99.0, 0.0], [99.0, 99.0], [0.0, 99.0]],
[[0.0, 0.0], [99.0, 0.0], [99.0, 99.0], [0.0, 99.0]],
],
device=device,
dtype=dtype,
),
"input_size": torch.tensor([[300, 300], [300, 300]], device=device, dtype=torch.int64),
"output_size": torch.tensor([[100, 100], [100, 100]], device=device, dtype=torch.long),
}
assert res.keys() == expected.keys()
assert_close(res["src"], expected["src"])
assert_close(res["dst"], expected["dst"])
assert_close(res["input_size"], expected["input_size"])
class TestRandomRectangleGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("height", [200])
@pytest.mark.parametrize("width", [300])
@pytest.mark.parametrize("scale", [torch.tensor([0.7, 1.1])])
@pytest.mark.parametrize("ratio", [torch.tensor([0.7, 1.1])])
@pytest.mark.parametrize("value", [0])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(
self,
batch_size,
height,
width,
scale,
ratio,
value,
same_on_batch,
device,
dtype,
):
RectangleEraseGenerator(
scale=scale.to(device=device, dtype=dtype),
ratio=ratio.to(device=device, dtype=dtype),
value=value,
)(torch.Size([batch_size, 1, height, width]), same_on_batch)
@pytest.mark.parametrize(
"height,width,scale,ratio,value",
[
(-100, 100, torch.tensor([0.7, 1.3]), torch.tensor([0.7, 1.3]), 0),
(100, -100, torch.tensor([0.7, 1.3]), torch.tensor([0.7, 1.3]), 0),
(100, -100, torch.tensor([0.7]), torch.tensor([0.7, 1.3]), 0),
(100, 100, torch.tensor([0.7, 1.3, 1.5]), torch.tensor([0.7, 1.3]), 0),
(100, 100, torch.tensor([0.7, 1.3]), torch.tensor([0.7]), 0),
(100, 100, torch.tensor([0.7, 1.3]), torch.tensor([0.7, 1.3, 1.5]), 0),
(100, 100, torch.tensor([0.7, 1.3]), torch.tensor([0.7, 1.3]), -1),
(100, 100, torch.tensor([0.7, 1.3]), torch.tensor([0.7, 1.3]), 2),
(
100,
100,
torch.tensor([0.5, 0.7]),
torch.tensor([0.7, 0.9]),
torch.tensor(0.5),
),
],
)
def test_invalid_param_combinations(self, height, width, scale, ratio, value, device, dtype):
batch_size = 8
with pytest.raises(Exception):
RectangleEraseGenerator(
scale=scale.to(device=device, dtype=dtype),
ratio=ratio.to(device=device, dtype=dtype),
value=value,
)(torch.Size([batch_size, 1, height, width]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
width, height = 100, 150
scale = torch.tensor([0.7, 1.3], device=device, dtype=dtype)
ratio = torch.tensor([0.7, 1.3], device=device, dtype=dtype)
value = 0.5
res = RectangleEraseGenerator(
scale=scale.to(device=device, dtype=dtype),
ratio=ratio.to(device=device, dtype=dtype),
value=value,
)(torch.Size([2, 1, height, width]))
expected = {
"widths": torch.tensor([100, 100], device=device, dtype=dtype),
"heights": torch.tensor([0, 0], device=device, dtype=dtype),
"xs": torch.tensor([0, 0], device=device, dtype=dtype),
"ys": torch.tensor([6, 8], device=device, dtype=dtype),
"values": torch.tensor([0.5000, 0.5000], device=device, dtype=dtype),
}
assert res.keys() == expected.keys()
assert_close(res["widths"], expected["widths"])
assert_close(res["widths"], expected["widths"])
assert_close(res["xs"], expected["xs"])
assert_close(res["ys"], expected["ys"])
assert_close(res["values"], expected["values"])
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
width, height = 100, 150
scale = torch.tensor([0.7, 1.3], device=device, dtype=dtype)
ratio = torch.tensor([0.7, 1.3], device=device, dtype=dtype)
value = 0.5
res = RectangleEraseGenerator(
scale=scale.to(device=device, dtype=dtype),
ratio=ratio.to(device=device, dtype=dtype),
value=value,
)(torch.Size([2, 1, height, width]), True)
expected = {
"widths": torch.tensor([100, 100], device=device, dtype=dtype),
"heights": torch.tensor([0, 0], device=device, dtype=dtype),
"xs": torch.tensor([0, 0], device=device, dtype=dtype),
"ys": torch.tensor([10, 10], device=device, dtype=dtype),
"values": torch.tensor([0.5000, 0.5000], device=device, dtype=dtype),
}
assert res.keys() == expected.keys()
assert_close(res["widths"], expected["widths"])
assert_close(res["widths"], expected["widths"])
assert_close(res["xs"], expected["xs"])
assert_close(res["ys"], expected["ys"])
assert_close(res["values"], expected["values"])
class TestCenterCropGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 2])
@pytest.mark.parametrize("height", [200])
@pytest.mark.parametrize("width", [200])
@pytest.mark.parametrize("size", [(100, 100)])
def test_valid_param_combinations(self, batch_size, height, width, size, device, dtype):
center_crop_generator(batch_size=batch_size, height=height, width=width, size=size)
@pytest.mark.parametrize(
"height,width,size",
[
(200, -200, (100, 100)),
(-200, 200, (100, 100)),
(100, 100, (120, 120)),
(150, 100, (120, 120)),
(100, 150, (120, 120)),
],
)
def test_invalid_param_combinations(self, height, width, size, device, dtype):
batch_size = 2
with pytest.raises(Exception):
center_crop_generator(batch_size=batch_size, height=height, width=width, size=size)
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
res = center_crop_generator(batch_size=2, height=200, width=200, size=(120, 150))
expected = {
"src": torch.tensor(
[
[[25, 40], [174, 40], [174, 159], [25, 159]],
[[25, 40], [174, 40], [174, 159], [25, 159]],
],
device=device,
dtype=torch.long,
),
"dst": torch.tensor(
[
[[0, 0], [149, 0], [149, 119], [0, 119]],
[[0, 0], [149, 0], [149, 119], [0, 119]],
],
device=device,
dtype=torch.long,
),
"input_size": torch.tensor([[200, 200], [200, 200]], device=device, dtype=torch.long),
"output_size": torch.tensor([[120, 150], [120, 150]], device=device, dtype=torch.long),
}
assert res.keys() == expected.keys()
assert_close(res["src"].to(device=device), expected["src"])
assert_close(res["dst"].to(device=device), expected["dst"])
def test_same_on_batch(self, device, dtype):
pass
class TestRandomMotionBlur(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("kernel_size", [3, (3, 5)])
@pytest.mark.parametrize("angle", [torch.tensor([10, 30])])
@pytest.mark.parametrize("direction", [torch.tensor([-1, -1]), torch.tensor([1, 1])])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, batch_size, kernel_size, angle, direction, same_on_batch, device, dtype):
MotionBlurGenerator(
kernel_size=kernel_size,
angle=angle.to(device=device, dtype=dtype),
direction=direction.to(device=device, dtype=dtype),
)(torch.Size([batch_size]), same_on_batch)
@pytest.mark.parametrize(
"kernel_size,angle,direction",
[
(4, torch.tensor([30, 100]), torch.tensor([-1, 1])),
(1, torch.tensor([30, 100]), torch.tensor([-1, 1])),
((1, 2, 3), torch.tensor([30, 100]), torch.tensor([-1, 1])),
(3, torch.tensor([30, 100]), torch.tensor([-2, 1])),
(3, torch.tensor([30, 100]), torch.tensor([-1, 2])),
],
)
def test_invalid_param_combinations(self, kernel_size, angle, direction, device, dtype):
with pytest.raises(Exception):
MotionBlurGenerator(
kernel_size=kernel_size,
angle=angle.to(device=device, dtype=dtype),
direction=direction.to(device=device, dtype=dtype),
)(torch.Size([8]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
angle = torch.tensor([30, 90])
direction = torch.tensor([-1, 1])
res = MotionBlurGenerator(
kernel_size=3,
angle=angle.to(device=device, dtype=dtype),
direction=direction.to(device=device, dtype=dtype),
)(torch.Size([2]))
expected = {
"ksize_factor": torch.tensor([3, 3], device=device, dtype=torch.int32),
"angle_factor": torch.tensor([82.9362, 84.9002], device=device, dtype=dtype),
"direction_factor": torch.tensor([-0.2343, 0.9186], device=device, dtype=dtype),
}
assert res.keys() == expected.keys()
assert_close(res["ksize_factor"], expected["ksize_factor"], rtol=1e-4, atol=1e-4)
assert_close(res["angle_factor"], expected["angle_factor"], rtol=1e-4, atol=1e-4)
assert_close(res["direction_factor"], expected["direction_factor"], rtol=1e-4, atol=1e-4)
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
angle = torch.tensor([30, 90])
direction = torch.tensor([-1, 1])
res = MotionBlurGenerator(
kernel_size=3,
angle=angle.to(device=device, dtype=dtype),
direction=direction.to(device=device, dtype=dtype),
)(torch.Size([2]), True)
expected = {
"ksize_factor": torch.tensor([3, 3], device=device, dtype=torch.int32),
"angle_factor": torch.tensor([82.9362, 82.9362], device=device, dtype=dtype),
"direction_factor": torch.tensor([0.8300, 0.8300], device=device, dtype=dtype),
}
assert res.keys() == expected.keys()
assert_close(res["ksize_factor"], expected["ksize_factor"], rtol=1e-4, atol=1e-4)
assert_close(res["angle_factor"], expected["angle_factor"], rtol=1e-4, atol=1e-4)
assert_close(res["direction_factor"], expected["direction_factor"], rtol=1e-4, atol=1e-4)
class TestRandomPosterizeGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("bits", [torch.tensor([0, 8])])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, batch_size, bits, same_on_batch, device, dtype):
PosterizeGenerator(bits)(torch.Size([batch_size]), same_on_batch)
@pytest.mark.parametrize(
"bits",
[
(torch.tensor([-1, 1])),
(torch.tensor([0, 9])),
(torch.tensor([3])),
([0, 8],),
],
)
def test_invalid_param_combinations(self, bits, device, dtype):
with pytest.raises(Exception):
if isinstance(bits, Tensor):
PosterizeGenerator(bits.to(device=device, dtype=dtype))(torch.Size([3]))
else:
PosterizeGenerator(bits)(torch.Size([3]))
def test_random_gen(self, device, dtype):
torch.manual_seed(9)
batch_size = 8
res = PosterizeGenerator(bits=torch.tensor([0, 8], device=device, dtype=dtype))(torch.Size([batch_size]))
expected = {"bits_factor": torch.tensor([5, 2, 4, 6, 7, 7, 2, 8], device=device, dtype=torch.int32)}
assert res.keys() == expected.keys()
assert_close(res["bits_factor"], expected["bits_factor"], rtol=1e-4, atol=1e-4)
def test_same_on_batch(self, device, dtype):
torch.manual_seed(9)
batch_size = 8
res = PosterizeGenerator(bits=torch.tensor([0, 8], device=device, dtype=dtype))(
torch.Size([batch_size]), same_on_batch=True
)
expected = {"bits_factor": torch.tensor([5, 5, 5, 5, 5, 5, 5, 5], device=device, dtype=torch.int32)}
assert res.keys() == expected.keys()
assert_close(res["bits_factor"], expected["bits_factor"], rtol=1e-4, atol=1e-4)
class TestPlainUniformGenerator(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("sharpness", [torch.tensor([0.0, 1.0])])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, batch_size, sharpness, same_on_batch, device, dtype):
PlainUniformGenerator(
(sharpness.to(device=device, dtype=dtype), "sharpness", None, None),
(sharpness.to(device=device, dtype=dtype), "sharpness_xx", 0.0, (0.0, 1.0)),
)(torch.Size([batch_size, 1]), same_on_batch)
@pytest.mark.parametrize("sharpness", [(torch.tensor([-1, 5])), (torch.tensor([3])), ([0, 1.0])])
def test_invalid_param_combinations(self, sharpness, device, dtype):
with pytest.raises(Exception):
PlainUniformGenerator(
(sharpness.to(device=device, dtype=dtype), "sharpness", None, None),
(
sharpness.to(device=device, dtype=dtype),
"sharpness",
0.0,
(0.0, 1.0),
),
)(torch.Size([8, 1]))
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
batch_size = 8
res = PlainUniformGenerator(
(
torch.tensor([0.0, 1.0], device=device, dtype=dtype),
"sharpness_factor",
None,
None,
)
)(torch.Size([batch_size, 1]))
expected = {
"sharpness_factor": torch.tensor(
[0.8823, 0.9150, 0.3829, 0.9593, 0.3904, 0.6009, 0.2566, 0.7936],
device=device,
dtype=dtype,
)
}
assert res.keys() == expected.keys()
assert_close(res["sharpness_factor"], expected["sharpness_factor"], rtol=1e-4, atol=1e-4)
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
batch_size = 8
res = PlainUniformGenerator(
(
torch.tensor([0.0, 1.0], device=device, dtype=dtype),
"sharpness_factor",
None,
None,
)
)(torch.Size([batch_size, 1]), True)
expected = {
"sharpness_factor": torch.tensor(
[0.8823, 0.8823, 0.8823, 0.8823, 0.8823, 0.8823, 0.8823, 0.8823],
device=device,
dtype=dtype,
)
}
assert res.keys() == expected.keys()
assert_close(res["sharpness_factor"], expected["sharpness_factor"], rtol=1e-4, atol=1e-4)
class TestRandomMixUpGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("p", [0.0, 0.5, 1.0])
@pytest.mark.parametrize("lambda_val", [None, torch.tensor([0.0, 1.0])])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(self, batch_size, p, lambda_val, same_on_batch, device, dtype):
MixupGenerator(
p=p,
lambda_val=(lambda_val.to(device=device, dtype=dtype) if isinstance(lambda_val, (Tensor)) else lambda_val),
)(torch.Size([batch_size, 3, 200, 200]), same_on_batch=same_on_batch)
@pytest.mark.parametrize(
"lambda_val",
[
(torch.tensor([-1, 1])),
(torch.tensor([0, 2])),
(torch.tensor([0, 0.5, 1])),
([0.0, 1.0]),
],
)
def test_invalid_param_combinations(self, lambda_val, device, dtype):
with pytest.raises(Exception):
MixupGenerator(p=1.0, lambda_val=lambda_val.to(device=device, dtype=dtype))(
torch.Size([8, 3, 200, 200]), same_on_batch=False
)
def test_random_gen(self, device, dtype):
if device.type != "cpu":
pytest.skip(
"Random number sequences differ between CPU and non-CPU devices; expected values computed on CPU"
)
torch.manual_seed(42)
batch_size = 8
res = MixupGenerator(p=0.5, lambda_val=torch.tensor([0.0, 1.0], device=device, dtype=dtype))(
torch.Size([batch_size, 3, 200, 200]), same_on_batch=False
)
expected = {
"mixup_pairs": torch.tensor([6, 1, 0, 7, 2, 5, 3, 4], device=device, dtype=torch.long),
"mixup_lambdas": torch.tensor(
[0.0000, 0.0000, 0.5739, 0.0000, 0.6274, 0.0000, 0.4414, 0.0000],
device=device,
dtype=dtype,
),
}
assert res.keys() == expected.keys()
assert_close(res["mixup_pairs"], expected["mixup_pairs"], rtol=1e-4, atol=1e-4)
assert_close(res["mixup_lambdas"], expected["mixup_lambdas"], rtol=1e-4, atol=1e-4)
def test_same_on_batch(self, device, dtype):
if device.type != "cpu":
pytest.skip(
"Random number sequences differ between CPU and non-CPU devices; expected values computed on CPU"
)
torch.manual_seed(9)
batch_size = 8
res = MixupGenerator(p=0.999999, lambda_val=torch.tensor([0.0, 1.0], device=device, dtype=dtype))(
torch.Size([batch_size, 3, 200, 200]), same_on_batch=True
)
expected = {
"mixup_pairs": torch.tensor([4, 6, 7, 5, 0, 1, 3, 2], device=device, dtype=torch.long),
"mixup_lambdas": torch.tensor(
[0.3804, 0.3804, 0.3804, 0.3804, 0.3804, 0.3804, 0.3804, 0.3804],
device=device,
dtype=dtype,
),
}
assert res.keys() == expected.keys()
assert_close(res["mixup_pairs"], expected["mixup_pairs"], rtol=1e-4, atol=1e-4)
assert_close(res["mixup_lambdas"], expected["mixup_lambdas"], rtol=1e-4, atol=1e-4)
class TestRandomCutMixGen(RandomGeneratorBaseTests):
@pytest.mark.parametrize("batch_size", [0, 1, 8])
@pytest.mark.parametrize("p", [0, 0.5, 1.0])
@pytest.mark.parametrize("width,height", [(200, 200)])
@pytest.mark.parametrize("num_mix", [1, 3])
@pytest.mark.parametrize("beta", [None, torch.tensor(1e-15), torch.tensor(1.0)])
@pytest.mark.parametrize("cut_size", [None, torch.tensor([0.0, 1.0]), torch.tensor([0.3, 0.6])])
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_valid_param_combinations(
self,
batch_size,
p,
width,
height,
num_mix,
beta,
cut_size,
same_on_batch,
device,
dtype,
):
CutmixGenerator(
p=p,
num_mix=num_mix,
beta=(beta.to(device=device, dtype=dtype) if isinstance(beta, (Tensor)) else beta),
cut_size=(cut_size.to(device=device, dtype=dtype) if isinstance(cut_size, (Tensor)) else cut_size),
)(torch.Size([batch_size, 3, height, width]), same_on_batch=same_on_batch)
@pytest.mark.parametrize(
"width,height,num_mix,beta,cut_size",
[
(200, -200, 1, None, None),
(-200, 200, 1, None, None),
(200, 200, 0, None, None),
(200, 200, 1.5, None, None),
(200, 200, 1, torch.tensor([0.0, 1.0]), None),
(200, 200, 1, None, torch.tensor([-1.0, 1.0])),
(200, 200, 1, None, torch.tensor([0.0, 2.0])),
],
)
@pytest.mark.parametrize("same_on_batch", [True, False])
def test_invalid_param_combinations(self, width, height, num_mix, beta, cut_size, same_on_batch, device, dtype):
with pytest.raises(Exception):
CutmixGenerator(
p=0.5,
num_mix=num_mix,
beta=(beta.to(device=device, dtype=dtype) if isinstance(beta, (Tensor)) else beta),
cut_size=(cut_size.to(device=device, dtype=dtype) if isinstance(cut_size, (Tensor)) else cut_size),
)(torch.Size([8, 3, height, width]), same_on_batch=same_on_batch)
def test_random_gen(self, device, dtype):
torch.manual_seed(42)
image_shape = torch.Size([8, 3, 200, 200])
res = CutmixGenerator(
p=0.5,
num_mix=1,
beta=torch.tensor(1.0, device=device, dtype=dtype),
cut_size=torch.tensor([0.0, 1.0], device=device, dtype=dtype),
)(image_shape, same_on_batch=False)
expected = {
"mix_pairs": torch.tensor([[1, 7, 5, 3, 6, 4, 2, 0]], device=device, dtype=torch.long),
"crop_src": torch.tensor(
[
[
[[48.0, 31.0], [47.0, 31.0], [47.0, 30.0], [48.0, 30.0]],
[[48.0, 31.0], [47.0, 31.0], [47.0, 30.0], [48.0, 30.0]],
[[17.0, 11.0], [141.0, 11.0], [141.0, 135.0], [17.0, 135.0]],
[[48.0, 31.0], [47.0, 31.0], [47.0, 30.0], [48.0, 30.0]],
[[16.0, 10.0], [147.0, 10.0], [147.0, 141.0], [16.0, 141.0]],
[[48.0, 31.0], [47.0, 31.0], [47.0, 30.0], [48.0, 30.0]],
[[8.0, 5.0], [171.0, 5.0], [171.0, 168.0], [8.0, 168.0]],
[[48.0, 31.0], [47.0, 31.0], [47.0, 30.0], [48.0, 30.0]],
]
],
device=device,
dtype=dtype,
),
"image_shape": image_shape,
}
assert res.keys() == expected.keys(), res.keys()
assert_close(res["mix_pairs"], expected["mix_pairs"], rtol=1e-4, atol=1e-4)
assert_close(res["crop_src"], expected["crop_src"], rtol=1e-4, atol=1e-4)
def test_same_on_batch(self, device, dtype):
torch.manual_seed(42)
image_shape = torch.Size([2, 3, 200, 200])
res = CutmixGenerator(
p=0.5,
num_mix=1,
beta=torch.tensor(1.0, device=device, dtype=dtype),
cut_size=torch.tensor([0.0, 1.0], device=device, dtype=dtype),
)(image_shape, same_on_batch=True)
expected = {
"mix_pairs": torch.tensor([[1, 0]], device=device, dtype=torch.long),
"crop_src": torch.tensor(
[
[
[[114, 53], [113, 53], [113, 52], [114, 52]],
[[114, 53], [113, 53], [113, 52], [114, 52]],
]
],
device=device,
dtype=dtype,
),
"image_shape": image_shape,
}
assert res.keys() == expected.keys(), res.keys()
assert_close(res["mix_pairs"], expected["mix_pairs"], rtol=1e-4, atol=1e-4)
assert_close(res["crop_src"], expected["crop_src"], rtol=1e-4, atol=1e-4)