diff --git a/README.md b/README.md index 4f61f17e9..8bf7acd05 100644 --- a/README.md +++ b/README.md @@ -129,7 +129,6 @@ Pixel-level transforms will change just an input image and will leave any additi - [GlassBlur](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.GlassBlur) - [HistogramMatching](https://albumentations.ai/docs/api_reference/augmentations/domain_adaptation/#albumentations.augmentations.domain_adaptation.HistogramMatching) - [HueSaturationValue](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.HueSaturationValue) -- [IAAAdditiveGaussianNoise](https://albumentations.ai/docs/api_reference/imgaug/transforms/#albumentations.imgaug.transforms.IAAAdditiveGaussianNoise) - [IAASuperpixels](https://albumentations.ai/docs/api_reference/imgaug/transforms/#albumentations.imgaug.transforms.IAASuperpixels) - [ISONoise](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.ISONoise) - [ImageCompression](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.ImageCompression) @@ -169,8 +168,6 @@ Spatial-level transforms will simultaneously change both an input image as well | [GridDropout](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.GridDropout) | ✓ | ✓ | | | | [HorizontalFlip](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.HorizontalFlip) | ✓ | ✓ | ✓ | ✓ | | [IAAAffine](https://albumentations.ai/docs/api_reference/imgaug/transforms/#albumentations.imgaug.transforms.IAAAffine) | ✓ | ✓ | ✓ | ✓ | -| [IAAFliplr](https://albumentations.ai/docs/api_reference/imgaug/transforms/#albumentations.imgaug.transforms.IAAFliplr) | ✓ | ✓ | ✓ | ✓ | -| [IAAFlipud](https://albumentations.ai/docs/api_reference/imgaug/transforms/#albumentations.imgaug.transforms.IAAFlipud) | ✓ | ✓ | ✓ | ✓ | | [IAAPiecewiseAffine](https://albumentations.ai/docs/api_reference/imgaug/transforms/#albumentations.imgaug.transforms.IAAPiecewiseAffine) | ✓ | ✓ | ✓ | ✓ | | [Lambda](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.Lambda) | ✓ | ✓ | ✓ | ✓ | | [LongestMaxSize](https://albumentations.ai/docs/api_reference/augmentations/geometric/resize/#albumentations.augmentations.geometric.resize.LongestMaxSize) | ✓ | ✓ | ✓ | ✓ | diff --git a/albumentations/augmentations/transforms.py b/albumentations/augmentations/transforms.py index 1455da12b..3c584169d 100644 --- a/albumentations/augmentations/transforms.py +++ b/albumentations/augmentations/transforms.py @@ -1688,6 +1688,8 @@ class GaussNoise(ImageOnlyTransform): var_limit ((float, float) or float): variance range for noise. If var_limit is a single float, the range will be (0, var_limit). Default: (10.0, 50.0). mean (float): mean of the noise. Default: 0 + per_channel (bool): if set to True, noise will be sampled for each channel independently. + Otherwise, the noise will be sampled once for all channels. Default: True p (float): probability of applying the transform. Default: 0.5. Targets: @@ -1697,7 +1699,7 @@ class GaussNoise(ImageOnlyTransform): uint8, float32 """ - def __init__(self, var_limit=(10.0, 50.0), mean=0, always_apply=False, p=0.5): + def __init__(self, var_limit=(10.0, 50.0), mean=0, per_channel=True, always_apply=False, p=0.5): super(GaussNoise, self).__init__(always_apply, p) if isinstance(var_limit, (tuple, list)): if var_limit[0] < 0: @@ -1716,6 +1718,7 @@ def __init__(self, var_limit=(10.0, 50.0), mean=0, always_apply=False, p=0.5): ) self.mean = mean + self.per_channel = per_channel def apply(self, img, gauss=None, **params): return F.gauss_noise(img, gauss=gauss) @@ -1726,7 +1729,13 @@ def get_params_dependent_on_targets(self, params): sigma = var ** 0.5 random_state = np.random.RandomState(random.randint(0, 2 ** 32 - 1)) - gauss = random_state.normal(self.mean, sigma, image.shape) + if self.per_channel: + gauss = random_state.normal(self.mean, sigma, image.shape) + else: + gauss = random_state.normal(self.mean, sigma, image.shape[:2]) + if len(image.shape) == 3: + gauss = np.expand_dims(gauss, -1) + return {"gauss": gauss} @property @@ -1734,7 +1743,7 @@ def targets_as_params(self): return ["image"] def get_transform_init_args_names(self): - return ("var_limit",) + return ("var_limit", "per_channel", "mean") class ISONoise(ImageOnlyTransform): diff --git a/albumentations/imgaug/transforms.py b/albumentations/imgaug/transforms.py index c63ff08f6..b4b1cdc80 100644 --- a/albumentations/imgaug/transforms.py +++ b/albumentations/imgaug/transforms.py @@ -98,7 +98,7 @@ def __init__( self.pad_mode = pad_mode self.pad_cval = pad_cval self.keep_size = keep_size - warnings.warn("This augmentation is deprecated. Please use CropAndPad instead", DeprecationWarning) + warnings.warn("IAACropAndPad is deprecated. Please use CropAndPad instead", FutureWarning) @property def processor(self): @@ -109,6 +109,10 @@ def get_transform_init_args_names(self): class IAAFliplr(DualIAATransform): + def __init__(self, always_apply=False, p=0.5): + super().__init__(always_apply, p) + warnings.warn("IAAFliplr is deprecated. Please use HorizontalFlip instead.", FutureWarning) + @property def processor(self): return iaa.Fliplr(1) @@ -118,6 +122,10 @@ def get_transform_init_args_names(self): class IAAFlipud(DualIAATransform): + def __init__(self, always_apply=False, p=0.5): + super().__init__(always_apply, p) + warnings.warn("IAAFlipud is deprecated. Please use VerticalFlip instead.", FutureWarning) + @property def processor(self): return iaa.Flipud(1) @@ -141,7 +149,7 @@ class IAAEmboss(Emboss): """ def __init__(self, alpha=(0.2, 0.5), strength=(0.2, 0.7), always_apply=False, p=0.5): - warnings.warn("This augmentation is deprecated. Please use Emboss instead", DeprecationWarning) + warnings.warn("IAAEmboss is deprecated. Please use Emboss instead", FutureWarning) super().__init__(alpha=alpha, strength=strength, always_apply=always_apply, p=p) @@ -186,7 +194,7 @@ class IAASharpen(Sharpen): """ def __init__(self, alpha=(0.2, 0.5), lightness=(0.5, 1.0), always_apply=False, p=0.5): - warnings.warn("This augmentation is deprecated. Please use Sharpen instead", DeprecationWarning) + warnings.warn("IAASharpen is deprecated. Please use Sharpen instead", FutureWarning) super().__init__(alpha=alpha, lightness=lightness, always_apply=always_apply, p=p) @@ -208,6 +216,7 @@ def __init__(self, loc=0, scale=(0.01 * 255, 0.05 * 255), per_channel=False, alw self.loc = loc self.scale = to_tuple(scale, 0.0) self.per_channel = per_channel + warnings.warn("IAAAdditiveGaussianNoise is deprecated. Please use GaussNoise instead", FutureWarning) @property def processor(self): @@ -321,5 +330,5 @@ class IAAPerspective(Perspective): """ def __init__(self, scale=(0.05, 0.1), keep_size=True, always_apply=False, p=0.5, **kwargs): - warnings.warn("This augmentation is deprecated. Please use Perspective instead", DeprecationWarning) + warnings.warn("IAAPerspective is deprecated. Please use Perspective instead", FutureWarning) super().__init__(scale=scale, keep_size=keep_size, always_apply=always_apply, p=p, **kwargs) diff --git a/tests/test_serialization.py b/tests/test_serialization.py index fc7688fa3..632821c3e 100644 --- a/tests/test_serialization.py +++ b/tests/test_serialization.py @@ -111,7 +111,7 @@ def test_augmentations_serialization(augmentation_cls, params, p, seed, image, m [A.MotionBlur, {"blur_limit": 3}], [A.MedianBlur, {"blur_limit": 3}], [A.GaussianBlur, {"blur_limit": 3}], - [A.GaussNoise, {"var_limit": (20, 90)}], + [A.GaussNoise, {"var_limit": (20, 90), "mean": 10, "per_channel": False}], [A.CLAHE, {"clip_limit": 2, "tile_grid_size": (12, 12)}], [A.RandomGamma, {"gamma_limit": (10, 90)}], [A.Cutout, {"num_holes": 4, "max_h_size": 4, "max_w_size": 4}], diff --git a/tools/make_transforms_docs.py b/tools/make_transforms_docs.py index 97151daab..cd230de05 100644 --- a/tools/make_transforms_docs.py +++ b/tools/make_transforms_docs.py @@ -52,7 +52,7 @@ def get_transforms_info(): transforms_info = {} for name, cls in inspect.getmembers(albumentations): if inspect.isclass(cls) and issubclass(cls, albumentations.BasicTransform) and name not in IGNORED_CLASSES: - if "DeprecationWarning" in inspect.getsource(cls): + if "DeprecationWarning" in inspect.getsource(cls) or "FutureWarning" in inspect.getsource(cls): continue targets = {Targets.IMAGE} @@ -132,24 +132,27 @@ def check_docs(filepath, image_only_transforms_links, dual_transforms_table): if line not in text: dual_lines_not_in_text.append(line) outdated_docs.update(["Spatial-level"]) - if not outdated_docs: - return - - raise ValueError( - "Docs for the following transform types are outdated: {outdated_docs_headers}. " - "Generate new docs by executing the `python tools/{py_file} make` command " - "and paste them to {filename}.\n" - "# Pixel-level transforms lines not in file:\n" - "{image_only_lines}\n" - "# Spatial-level transforms lines not in file:\n" - "{dual_lines}".format( - outdated_docs_headers=", ".join(outdated_docs), - py_file=os.path.basename(os.path.realpath(__file__)), - filename=os.path.basename(filepath), - image_only_lines="\n".join(image_only_lines_not_in_text), - dual_lines="\n".join(dual_lines_not_in_text), + if outdated_docs: + raise ValueError( + "Docs for the following transform types are outdated: {outdated_docs_headers}. " + "Generate new docs by executing the `python tools/{py_file} make` command " + "and paste them to {filename}.\n" + "# Pixel-level transforms lines not in file:\n" + "{image_only_lines}\n" + "# Spatial-level transforms lines not in file:\n" + "{dual_lines}".format( + outdated_docs_headers=", ".join(outdated_docs), + py_file=os.path.basename(os.path.realpath(__file__)), + filename=os.path.basename(filepath), + image_only_lines="\n".join(image_only_lines_not_in_text), + dual_lines="\n".join(dual_lines_not_in_text), + ) ) - ) + + if image_only_transforms_links not in text: + raise ValueError("Image only transforms links are outdated.") + if dual_transforms_table not in text: + raise ValueError("Dual transforms table are outdated.") def main():