Skip to content

Commit 393f01c

Browse files
committed
fix(augment): align Kornia GaussianBlur/GaussNoise defaults with albumentations
Two Kornia factory defaults did not match the Albumentations defaults they stand in for, so switching augmentation_backend silently changed augmentation strength for the same aug_config. GaussianBlur sigma defaulted to Kornia's own (0.1, 2.0) while the albumentations default is (0.5, 3.0), so an unspecified sigma blurred less on the GPU path. The call-site comment claimed the opposite. AUG_INDUSTRIAL reaches this default (it sets blur_limit but no sigma). GaussNoise std_range defaulted to rf-detr's own (0.01, 0.05) against the albumentations default (0.2, 0.44) on the same 0-1 image scale, 4-9x weaker, and the divergence warning reported rf-detr's own range as if it were albumentations'. The default is now the albumentations one; the warning text is unchanged and still correct for an explicit range. Doc table updated; regression tests pin both defaults to the live albumentations values.
1 parent a700efc commit 393f01c

3 files changed

Lines changed: 65 additions & 4 deletions

File tree

src/rfdetr/datasets/aug_configs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
| ``Affine`` | ``K.RandomAffine`` | ``translate_percent`` treated as fraction |
8181
| ``ColorJitter`` | ``K.ColorJiggle`` | Same multiplicative semantics |
8282
| ``RandomBrightnessContrast`` | ``K.ColorJiggle`` | ``brightness_limit`` / ``contrast_limit`` direct |
83-
| ``GaussianBlur`` | ``K.RandomGaussianBlur`` | ``blur_limit`` rounded up to odd; ``sigma=(0.1, 2.0)`` |
83+
| ``GaussianBlur`` | ``K.RandomGaussianBlur`` | ``blur_limit`` rounded up to odd; ``sigma`` defaults to the albumentations (0.5, 3.0) |
8484
| ``GaussNoise`` | ``K.RandomGaussianNoise`` | Upper bound of ``std_range`` used as fixed std |
8585
8686
Segmentation models are supported by the GPU augmentation path; masks are augmented in sync with images and boxes.

src/rfdetr/datasets/kornia_transforms.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,8 +369,11 @@ def _make_gaussian_blur(params: dict[str, Any]) -> Any:
369369
if blur_limit % 2 == 0:
370370
blur_limit = blur_limit + 1
371371
blur_limit = max(3, blur_limit)
372-
# Match the CPU albumentations default sigma range while allowing an explicit override via config.
373-
sigma_range = params.get("sigma", (0.1, 2.0))
372+
# Default to the CPU (albumentations) GaussianBlur sigma_limit default, (0.5, 3.0), so the same
373+
# aug_config blurs by the same amount on either backend. The previous default (0.1, 2.0) is Kornia's
374+
# own convention, not Albumentations', so an unspecified sigma blurred noticeably less on the GPU path;
375+
# AUG_INDUSTRIAL reaches this default (it sets blur_limit but no sigma). An explicit sigma still wins.
376+
sigma_range = params.get("sigma", (0.5, 3.0))
374377
blur_sigma = tuple(sigma_range) if len(sigma_range) == 2 else (sigma_range[0], sigma_range[0])
375378
return RandomGaussianBlur(
376379
kernel_size=(blur_limit, blur_limit),
@@ -385,10 +388,14 @@ def _make_gauss_noise(params: dict[str, Any]) -> Any:
385388
Kornia takes a single ``std`` value, so the upper bound of ``std_range`` is used as a fixed standard deviation. When
386389
the configured range is non-degenerate this diverges from the CPU (albumentations) path, which samples a fresh std
387390
per call; a warning is emitted at build time so the drift is visible.
391+
392+
The default matches the CPU (albumentations) ``GaussNoise.std_range`` default, ``(0.2, 0.44)`` on the 0-1 image
393+
scale both backends use, so an unspecified ``std_range`` adds the same amount of noise on either path. The previous
394+
default ``(0.01, 0.05)`` was rf-detr's own, 4-9x weaker than the CPU backend for the same config.
388395
"""
389396
from kornia.augmentation import RandomGaussianNoise
390397

391-
std_range = params.get("std_range", (0.01, 0.05))
398+
std_range = params.get("std_range", (0.2, 0.44))
392399
if std_range[0] != std_range[1]:
393400
logger.warning(
394401
"GPU augmentation (Kornia) uses fixed std=%.3f for GaussianNoise "

tests/datasets/test_kornia_transforms.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,60 @@ def test_no_warning_for_degenerate_std_range(self):
730730
mock_warning.assert_not_called()
731731

732732

733+
class TestGaussianDefaultsMatchAlbumentations:
734+
"""The unspecified GaussianBlur sigma and GaussNoise std defaults must match the
735+
Albumentations defaults they stand in for (issue #1351): the same aug_config with no
736+
explicit value should augment by the same amount on either backend."""
737+
738+
@pytest.fixture(autouse=True)
739+
def _require_kornia(self):
740+
pytest.importorskip("kornia")
741+
742+
def test_gaussian_blur_sigma_default_matches_albumentations(self):
743+
"""An unspecified sigma must equal albumentations' GaussianBlur sigma_limit default."""
744+
albumentations = pytest.importorskip("albumentations")
745+
746+
from rfdetr.datasets import kornia_transforms
747+
748+
cpu_default = tuple(albumentations.GaussianBlur().sigma_limit)
749+
transform = kornia_transforms._make_gaussian_blur({"blur_limit": 3, "p": 0.3})
750+
gpu_default = tuple(float(v) for v in transform._param_generator.sigma)
751+
752+
assert gpu_default == pytest.approx(cpu_default), (
753+
f"unspecified GaussianBlur sigma is {gpu_default} on the GPU path but "
754+
f"{cpu_default} on the CPU path, so the same config blurs by different amounts"
755+
)
756+
757+
def test_gauss_noise_std_default_matches_albumentations(self):
758+
"""An unspecified std_range must equal albumentations' GaussNoise std_range default."""
759+
albumentations = pytest.importorskip("albumentations")
760+
761+
from rfdetr.datasets import kornia_transforms
762+
763+
cpu_default = tuple(albumentations.GaussNoise().std_range)
764+
# Kornia takes a single std (the range's upper bound); the DEFAULT range must still
765+
# be the albumentations one, so an unspecified config lands on the same upper bound.
766+
transform = kornia_transforms._make_gauss_noise({"p": 0.3})
767+
gpu_std = float(transform.flags["std"])
768+
769+
assert gpu_std == pytest.approx(cpu_default[1]), (
770+
f"unspecified GaussNoise std is {gpu_std} on the GPU path but the CPU path "
771+
f"samples up to {cpu_default[1]}, so the same config adds different noise"
772+
)
773+
774+
def test_default_gauss_noise_warns_because_the_default_range_is_non_degenerate(self):
775+
"""The albumentations default range is non-degenerate, so building with no std_range
776+
still emits the fixed-std divergence warning rather than going silent."""
777+
from unittest import mock
778+
779+
from rfdetr.datasets import kornia_transforms
780+
781+
with mock.patch.object(kornia_transforms.logger, "warning") as mock_warning:
782+
kornia_transforms._make_gauss_noise({"p": 0.3})
783+
784+
mock_warning.assert_called_once()
785+
786+
733787
# ---------------------------------------------------------------------------
734788
# TestResolveAugmentationBackend — the single resolution seam that maps backend
735789
# strings (incl. sentinels/legacy aliases) to concrete AugmentationBackend members.

0 commit comments

Comments
 (0)