nrtk-albumentations 2.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nrtk-albumentations might be problematic. Click here for more details.

Files changed (62) hide show
  1. albumentations/__init__.py +21 -0
  2. albumentations/augmentations/__init__.py +23 -0
  3. albumentations/augmentations/blur/__init__.py +0 -0
  4. albumentations/augmentations/blur/functional.py +438 -0
  5. albumentations/augmentations/blur/transforms.py +1633 -0
  6. albumentations/augmentations/crops/__init__.py +0 -0
  7. albumentations/augmentations/crops/functional.py +494 -0
  8. albumentations/augmentations/crops/transforms.py +3647 -0
  9. albumentations/augmentations/dropout/__init__.py +0 -0
  10. albumentations/augmentations/dropout/channel_dropout.py +134 -0
  11. albumentations/augmentations/dropout/coarse_dropout.py +567 -0
  12. albumentations/augmentations/dropout/functional.py +1017 -0
  13. albumentations/augmentations/dropout/grid_dropout.py +166 -0
  14. albumentations/augmentations/dropout/mask_dropout.py +274 -0
  15. albumentations/augmentations/dropout/transforms.py +461 -0
  16. albumentations/augmentations/dropout/xy_masking.py +186 -0
  17. albumentations/augmentations/geometric/__init__.py +0 -0
  18. albumentations/augmentations/geometric/distortion.py +1238 -0
  19. albumentations/augmentations/geometric/flip.py +752 -0
  20. albumentations/augmentations/geometric/functional.py +4151 -0
  21. albumentations/augmentations/geometric/pad.py +676 -0
  22. albumentations/augmentations/geometric/resize.py +956 -0
  23. albumentations/augmentations/geometric/rotate.py +864 -0
  24. albumentations/augmentations/geometric/transforms.py +1962 -0
  25. albumentations/augmentations/mixing/__init__.py +0 -0
  26. albumentations/augmentations/mixing/domain_adaptation.py +787 -0
  27. albumentations/augmentations/mixing/domain_adaptation_functional.py +453 -0
  28. albumentations/augmentations/mixing/functional.py +878 -0
  29. albumentations/augmentations/mixing/transforms.py +832 -0
  30. albumentations/augmentations/other/__init__.py +0 -0
  31. albumentations/augmentations/other/lambda_transform.py +180 -0
  32. albumentations/augmentations/other/type_transform.py +261 -0
  33. albumentations/augmentations/pixel/__init__.py +0 -0
  34. albumentations/augmentations/pixel/functional.py +4226 -0
  35. albumentations/augmentations/pixel/transforms.py +7556 -0
  36. albumentations/augmentations/spectrogram/__init__.py +0 -0
  37. albumentations/augmentations/spectrogram/transform.py +220 -0
  38. albumentations/augmentations/text/__init__.py +0 -0
  39. albumentations/augmentations/text/functional.py +272 -0
  40. albumentations/augmentations/text/transforms.py +299 -0
  41. albumentations/augmentations/transforms3d/__init__.py +0 -0
  42. albumentations/augmentations/transforms3d/functional.py +393 -0
  43. albumentations/augmentations/transforms3d/transforms.py +1422 -0
  44. albumentations/augmentations/utils.py +249 -0
  45. albumentations/core/__init__.py +0 -0
  46. albumentations/core/bbox_utils.py +920 -0
  47. albumentations/core/composition.py +1885 -0
  48. albumentations/core/hub_mixin.py +299 -0
  49. albumentations/core/keypoints_utils.py +521 -0
  50. albumentations/core/label_manager.py +339 -0
  51. albumentations/core/pydantic.py +239 -0
  52. albumentations/core/serialization.py +352 -0
  53. albumentations/core/transforms_interface.py +976 -0
  54. albumentations/core/type_definitions.py +127 -0
  55. albumentations/core/utils.py +605 -0
  56. albumentations/core/validation.py +129 -0
  57. albumentations/pytorch/__init__.py +1 -0
  58. albumentations/pytorch/transforms.py +189 -0
  59. nrtk_albumentations-2.1.0.dist-info/METADATA +196 -0
  60. nrtk_albumentations-2.1.0.dist-info/RECORD +62 -0
  61. nrtk_albumentations-2.1.0.dist-info/WHEEL +4 -0
  62. nrtk_albumentations-2.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,166 @@
1
+ """Implementation of grid-based dropout augmentation.
2
+
3
+ This module provides GridDropout, which creates a regular grid over the image and drops out
4
+ rectangular regions according to the specified grid pattern. Unlike random dropout methods,
5
+ grid dropout enforces a structured pattern of occlusions that can help models learn spatial
6
+ relationships and context across the entire image space.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Annotated, Any, Literal
12
+
13
+ from pydantic import AfterValidator, Field
14
+
15
+ import albumentations.augmentations.dropout.functional as fdropout
16
+ from albumentations.augmentations.dropout.transforms import BaseDropout
17
+ from albumentations.core.pydantic import check_range_bounds, nondecreasing
18
+
19
+ __all__ = ["GridDropout"]
20
+
21
+
22
+ class GridDropout(BaseDropout):
23
+ """Apply GridDropout augmentation to images, masks, bounding boxes, and keypoints.
24
+
25
+ GridDropout drops out rectangular regions of an image and the corresponding mask in a grid fashion.
26
+ This technique can help improve model robustness by forcing the network to rely on a broader context
27
+ rather than specific local features.
28
+
29
+ Args:
30
+ ratio (float): The ratio of the mask holes to the unit size (same for horizontal and vertical directions).
31
+ Must be between 0 and 1. Default: 0.5.
32
+ unit_size_range (tuple[int, int] | None): Range from which to sample grid size. Default: None.
33
+ Must be between 2 and the image's shorter edge. If None, grid size is calculated based on image size.
34
+ holes_number_xy (tuple[int, int] | None): The number of grid units in x and y directions.
35
+ First value should be between 1 and image width//2,
36
+ Second value should be between 1 and image height//2.
37
+ Default: None. If provided, overrides unit_size_range.
38
+ random_offset (bool): Whether to offset the grid randomly between 0 and (grid unit size - hole size).
39
+ If True, entered shift_xy is ignored and set randomly. Default: True.
40
+ fill (tuple[float, float] | float | Literal["random", "random_uniform", "inpaint_telea", "inpaint_ns"]):
41
+ Value for the dropped pixels. Can be:
42
+ - int or float: all channels are filled with this value
43
+ - tuple: tuple of values for each channel
44
+ - 'random': each pixel is filled with random values
45
+ - 'random_uniform': each hole is filled with a single random color
46
+ - 'inpaint_telea': uses OpenCV Telea inpainting method
47
+ - 'inpaint_ns': uses OpenCV Navier-Stokes inpainting method
48
+ Default: 0
49
+ fill_mask (tuple[float, float] | float | None): Value for the dropped pixels in mask.
50
+ If None, the mask is not modified. Default: None.
51
+ shift_xy (tuple[int, int]): Offsets of the grid start in x and y directions from (0,0) coordinate.
52
+ Only used when random_offset is False. Default: (0, 0).
53
+ p (float): Probability of applying the transform. Default: 0.5.
54
+
55
+ Targets:
56
+ image, mask, bboxes, keypoints, volume, mask3d
57
+
58
+ Image types:
59
+ uint8, float32
60
+
61
+ Note:
62
+ - If both unit_size_range and holes_number_xy are None, the grid size is calculated based on the image size.
63
+ - The actual number of dropped regions may differ slightly from holes_number_xy due to rounding.
64
+ - Inpainting methods ('inpaint_telea', 'inpaint_ns') work only with grayscale or RGB images.
65
+ - For 'random_uniform' fill, each grid cell gets a single random color, unlike 'random' where each pixel
66
+ gets its own random value.
67
+
68
+ Example:
69
+ >>> import numpy as np
70
+ >>> import albumentations as A
71
+ >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
72
+ >>> mask = np.random.randint(0, 2, (100, 100), dtype=np.uint8)
73
+ >>> # Example with standard fill value
74
+ >>> aug_basic = A.GridDropout(
75
+ ... ratio=0.3,
76
+ ... unit_size_range=(10, 20),
77
+ ... random_offset=True,
78
+ ... p=1.0
79
+ ... )
80
+ >>> # Example with random uniform fill
81
+ >>> aug_random = A.GridDropout(
82
+ ... ratio=0.3,
83
+ ... unit_size_range=(10, 20),
84
+ ... fill="random_uniform",
85
+ ... p=1.0
86
+ ... )
87
+ >>> # Example with inpainting
88
+ >>> aug_inpaint = A.GridDropout(
89
+ ... ratio=0.3,
90
+ ... unit_size_range=(10, 20),
91
+ ... fill="inpaint_ns",
92
+ ... p=1.0
93
+ ... )
94
+ >>> transformed = aug_random(image=image, mask=mask)
95
+ >>> transformed_image, transformed_mask = transformed["image"], transformed["mask"]
96
+
97
+ Reference:
98
+ - Paper: https://arxiv.org/abs/2001.04086
99
+ - OpenCV Inpainting methods: https://docs.opencv.org/master/df/d3d/tutorial_py_inpainting.html
100
+
101
+ """
102
+
103
+ class InitSchema(BaseDropout.InitSchema):
104
+ ratio: float = Field(gt=0, le=1)
105
+
106
+ random_offset: bool
107
+
108
+ unit_size_range: (
109
+ Annotated[tuple[int, int], AfterValidator(check_range_bounds(2, None)), AfterValidator(nondecreasing)]
110
+ | None
111
+ )
112
+ shift_xy: Annotated[tuple[int, int], AfterValidator(check_range_bounds(0, None))]
113
+
114
+ holes_number_xy: Annotated[tuple[int, int], AfterValidator(check_range_bounds(1, None))] | None
115
+
116
+ def __init__(
117
+ self,
118
+ ratio: float = 0.5,
119
+ random_offset: bool = True,
120
+ unit_size_range: tuple[int, int] | None = None,
121
+ holes_number_xy: tuple[int, int] | None = None,
122
+ shift_xy: tuple[int, int] = (0, 0),
123
+ fill: tuple[float, ...] | float | Literal["random", "random_uniform", "inpaint_telea", "inpaint_ns"] = 0,
124
+ fill_mask: tuple[float, ...] | float | None = None,
125
+ p: float = 0.5,
126
+ ):
127
+ super().__init__(fill=fill, fill_mask=fill_mask, p=p)
128
+ self.ratio = ratio
129
+ self.unit_size_range = unit_size_range
130
+ self.holes_number_xy = holes_number_xy
131
+ self.random_offset = random_offset
132
+ self.shift_xy = shift_xy
133
+
134
+ def get_params_dependent_on_data(self, params: dict[str, Any], data: dict[str, Any]) -> dict[str, Any]:
135
+ """Get parameters dependent on the data.
136
+
137
+ Args:
138
+ params (dict[str, Any]): Dictionary containing parameters.
139
+ data (dict[str, Any]): Dictionary containing data.
140
+
141
+ Returns:
142
+ dict[str, Any]: Dictionary with parameters for transformation.
143
+
144
+ """
145
+ image_shape = params["shape"]
146
+ if self.holes_number_xy:
147
+ grid = self.holes_number_xy
148
+ else:
149
+ # Calculate grid based on unit_size_range or default
150
+ unit_height, unit_width = fdropout.calculate_grid_dimensions(
151
+ image_shape,
152
+ self.unit_size_range,
153
+ self.holes_number_xy,
154
+ self.random_generator,
155
+ )
156
+ grid = (image_shape[0] // unit_height, image_shape[1] // unit_width)
157
+
158
+ holes = fdropout.generate_grid_holes(
159
+ image_shape,
160
+ grid,
161
+ self.ratio,
162
+ self.random_offset,
163
+ self.shift_xy,
164
+ self.random_generator,
165
+ )
166
+ return {"holes": holes, "seed": self.random_generator.integers(0, 2**32 - 1)}
@@ -0,0 +1,274 @@
1
+ """Implementation of mask-based dropout augmentation.
2
+
3
+ This module provides the MaskDropout transform, which identifies objects in a segmentation mask
4
+ and drops out random objects completely. This augmentation is particularly useful for instance
5
+ segmentation and object detection tasks, as it simulates occlusions or missing objects in a
6
+ semantically meaningful way, rather than dropping out random pixels or regions.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from typing import Any, Literal, cast
12
+
13
+ import cv2
14
+ import numpy as np
15
+
16
+ import albumentations.augmentations.dropout.functional as fdropout
17
+ from albumentations.core.bbox_utils import BboxProcessor, denormalize_bboxes, normalize_bboxes
18
+ from albumentations.core.keypoints_utils import KeypointsProcessor
19
+ from albumentations.core.pydantic import OnePlusIntRangeType
20
+ from albumentations.core.transforms_interface import BaseTransformInitSchema, DualTransform
21
+ from albumentations.core.type_definitions import ALL_TARGETS
22
+
23
+ __all__ = ["MaskDropout"]
24
+
25
+
26
+ class MaskDropout(DualTransform):
27
+ """Apply dropout to random objects in a mask, zeroing out the corresponding regions in both the image and mask.
28
+
29
+ This transform identifies objects in the mask (where each unique non-zero value represents a distinct object),
30
+ randomly selects a number of these objects, and sets their corresponding regions to zero in both the image and mask.
31
+ It can also handle bounding boxes and keypoints, removing or adjusting them based on the dropout regions.
32
+
33
+ Args:
34
+ max_objects (int | tuple[int, int]): Maximum number of objects to dropout. If a single int is provided,
35
+ it's treated as the upper bound. If a tuple of two ints is provided, it's treated as a range [min, max].
36
+ fill (float | Literal["inpaint_telea", "inpaint_ns"]): Value to fill dropped out regions in the image.
37
+ Can be one of:
38
+ - float: Constant value to fill the regions (e.g., 0 for black, 255 for white)
39
+ - "inpaint_telea": Use Telea inpainting algorithm (for 3-channel images only)
40
+ - "inpaint_ns": Use Navier-Stokes inpainting algorithm (for 3-channel images only)
41
+ fill_mask (float): Value to fill the dropped out regions in the mask.
42
+ min_area (float): Minimum area (in pixels) of a bounding box that must remain visible after dropout to be kept.
43
+ Only applicable if bounding box augmentation is enabled. Default: 0.0
44
+ min_visibility (float): Minimum visibility ratio (visible area / total area) of a bounding box after dropout
45
+ to be kept. Only applicable if bounding box augmentation is enabled. Default: 0.0
46
+ p (float): Probability of applying the transform. Default: 0.5.
47
+
48
+ Targets:
49
+ image, mask, bboxes, keypoints, volume, mask3d
50
+
51
+ Image types:
52
+ uint8, float32
53
+
54
+ Note:
55
+ - The mask should be a single-channel image where 0 represents the background and non-zero values represent
56
+ different object instances.
57
+ - For bounding box and keypoint augmentation, make sure to set up the corresponding processors in the pipeline.
58
+
59
+ Examples:
60
+ >>> import numpy as np
61
+ >>> import albumentations as A
62
+ >>>
63
+ >>> # Prepare sample data
64
+ >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
65
+ >>> mask = np.zeros((100, 100), dtype=np.uint8)
66
+ >>> mask[20:40, 20:40] = 1 # Object 1
67
+ >>> mask[60:80, 60:80] = 2 # Object 2
68
+ >>> bboxes = np.array([[20, 20, 40, 40], [60, 60, 80, 80]], dtype=np.float32)
69
+ >>> bbox_labels = [1, 2]
70
+ >>> keypoints = np.array([[30, 30], [70, 70]], dtype=np.float32)
71
+ >>> keypoint_labels = [0, 1]
72
+ >>>
73
+ >>> # Define the transform with tuple for max_objects
74
+ >>> transform = A.Compose(
75
+ ... transforms=[
76
+ ... A.MaskDropout(
77
+ ... max_objects=(1, 2), # Using tuple to specify min and max objects to drop
78
+ ... fill=0, # Fill value for dropped regions in image
79
+ ... fill_mask=0, # Fill value for dropped regions in mask
80
+ ... p=1.0
81
+ ... ),
82
+ ... ],
83
+ ... bbox_params=A.BboxParams(
84
+ ... format='pascal_voc',
85
+ ... label_fields=['bbox_labels'],
86
+ ... min_area=1,
87
+ ... min_visibility=0.1
88
+ ... ),
89
+ ... keypoint_params=A.KeypointParams(
90
+ ... format='xy',
91
+ ... label_fields=['keypoint_labels'],
92
+ ... remove_invisible=True
93
+ ... )
94
+ ... )
95
+ >>>
96
+ >>> # Apply the transform
97
+ >>> transformed = transform(
98
+ ... image=image,
99
+ ... mask=mask,
100
+ ... bboxes=bboxes,
101
+ ... bbox_labels=bbox_labels,
102
+ ... keypoints=keypoints,
103
+ ... keypoint_labels=keypoint_labels
104
+ ... )
105
+ >>>
106
+ >>> # Get the transformed data
107
+ >>> transformed_image = transformed['image'] # Image with dropped out regions
108
+ >>> transformed_mask = transformed['mask'] # Mask with dropped out regions
109
+ >>> transformed_bboxes = transformed['bboxes'] # Remaining bboxes after dropout
110
+ >>> transformed_bbox_labels = transformed['bbox_labels'] # Labels for remaining bboxes
111
+ >>> transformed_keypoints = transformed['keypoints'] # Remaining keypoints after dropout
112
+ >>> transformed_keypoint_labels = transformed['keypoint_labels'] # Labels for remaining keypoints
113
+
114
+ """
115
+
116
+ _targets = ALL_TARGETS
117
+
118
+ class InitSchema(BaseTransformInitSchema):
119
+ max_objects: OnePlusIntRangeType
120
+
121
+ fill: float | Literal["inpaint_telea", "inpaint_ns"]
122
+ fill_mask: float
123
+
124
+ def __init__(
125
+ self,
126
+ max_objects: tuple[int, int] | int = (1, 1),
127
+ fill: float | Literal["inpaint_telea", "inpaint_ns"] = 0,
128
+ fill_mask: float = 0,
129
+ p: float = 0.5,
130
+ ):
131
+ super().__init__(p=p)
132
+ self.max_objects = cast("tuple[int, int]", max_objects)
133
+ self.fill = fill # type: ignore[assignment]
134
+ self.fill_mask = fill_mask
135
+
136
+ @property
137
+ def targets_as_params(self) -> list[str]:
138
+ """Get targets as parameters.
139
+
140
+ Returns:
141
+ list[str]: List of targets as parameters.
142
+
143
+ """
144
+ return ["mask"]
145
+
146
+ def get_params_dependent_on_data(self, params: dict[str, Any], data: dict[str, Any]) -> dict[str, Any]:
147
+ """Get parameters dependent on the data.
148
+
149
+ Args:
150
+ params (dict[str, Any]): Dictionary containing parameters.
151
+ data (dict[str, Any]): Dictionary containing data.
152
+
153
+ Returns:
154
+ dict[str, Any]: Dictionary with parameters for transformation.
155
+
156
+ """
157
+ mask = data["mask"]
158
+
159
+ label_image, num_labels = fdropout.label(mask, return_num=True)
160
+
161
+ if num_labels == 0:
162
+ dropout_mask = None
163
+ else:
164
+ objects_to_drop = self.py_random.randint(*self.max_objects)
165
+ objects_to_drop = min(num_labels, objects_to_drop)
166
+
167
+ if objects_to_drop == num_labels:
168
+ dropout_mask = mask > 0
169
+ else:
170
+ labels_index = self.py_random.sample(range(1, num_labels + 1), objects_to_drop)
171
+ dropout_mask = np.zeros(mask.shape[:2], dtype=bool)
172
+ for label_index in labels_index:
173
+ dropout_mask |= label_image == label_index
174
+
175
+ return {"dropout_mask": dropout_mask}
176
+
177
+ def apply(self, img: np.ndarray, dropout_mask: np.ndarray | None, **params: Any) -> np.ndarray:
178
+ """Apply dropout to the image.
179
+
180
+ Args:
181
+ img (np.ndarray): The image to apply the transform to.
182
+ dropout_mask (np.ndarray | None): The dropout mask for the image.
183
+ **params (Any): Additional parameters for the transform.
184
+
185
+ Returns:
186
+ np.ndarray: The transformed image.
187
+
188
+ """
189
+ if dropout_mask is None:
190
+ return img
191
+
192
+ if self.fill in {"inpaint_telea", "inpaint_ns"}:
193
+ dropout_mask = dropout_mask.astype(np.uint8)
194
+ _, _, width, height = cv2.boundingRect(dropout_mask)
195
+ radius = min(3, max(width, height) // 2)
196
+ return cv2.inpaint(img, dropout_mask, radius, cast("Literal['inpaint_telea', 'inpaint_ns']", self.fill))
197
+
198
+ img = img.copy()
199
+ img[dropout_mask] = self.fill
200
+
201
+ return img
202
+
203
+ def apply_to_mask(self, mask: np.ndarray, dropout_mask: np.ndarray | None, **params: Any) -> np.ndarray:
204
+ """Apply dropout to the mask.
205
+
206
+ Args:
207
+ mask (np.ndarray): The mask to apply the transform to.
208
+ dropout_mask (np.ndarray | None): The dropout mask for the mask.
209
+ **params (Any): Additional parameters for the transform.
210
+
211
+ Returns:
212
+ np.ndarray: The transformed mask.
213
+
214
+ """
215
+ if dropout_mask is None or self.fill_mask is None:
216
+ return mask
217
+
218
+ mask = mask.copy()
219
+ mask[dropout_mask] = self.fill_mask
220
+ return mask
221
+
222
+ def apply_to_bboxes(self, bboxes: np.ndarray, dropout_mask: np.ndarray | None, **params: Any) -> np.ndarray:
223
+ """Apply dropout to bounding boxes.
224
+
225
+ Args:
226
+ bboxes (np.ndarray): The bounding boxes to apply the transform to.
227
+ dropout_mask (np.ndarray | None): The dropout mask for the bounding boxes.
228
+ **params (Any): Additional parameters for the transform.
229
+
230
+ Returns:
231
+ np.ndarray: The transformed bounding boxes.
232
+
233
+ """
234
+ if dropout_mask is None:
235
+ return bboxes
236
+
237
+ processor = cast("BboxProcessor", self.get_processor("bboxes"))
238
+ if processor is None:
239
+ return bboxes
240
+
241
+ image_shape = params["shape"][:2]
242
+
243
+ denormalized_bboxes = denormalize_bboxes(bboxes, image_shape)
244
+
245
+ result = fdropout.mask_dropout_bboxes(
246
+ denormalized_bboxes,
247
+ dropout_mask,
248
+ image_shape,
249
+ processor.params.min_area,
250
+ processor.params.min_visibility,
251
+ )
252
+
253
+ return normalize_bboxes(result, image_shape)
254
+
255
+ def apply_to_keypoints(self, keypoints: np.ndarray, dropout_mask: np.ndarray | None, **params: Any) -> np.ndarray:
256
+ """Apply dropout to keypoints.
257
+
258
+ Args:
259
+ keypoints (np.ndarray): The keypoints to apply the transform to.
260
+ dropout_mask (np.ndarray | None): The dropout mask for the keypoints.
261
+ **params (Any): Additional parameters for the transform.
262
+
263
+ Returns:
264
+ np.ndarray: The transformed keypoints.
265
+
266
+ """
267
+ if dropout_mask is None:
268
+ return keypoints
269
+ processor = cast("KeypointsProcessor", self.get_processor("keypoints"))
270
+
271
+ if processor is None or not processor.params.remove_invisible:
272
+ return keypoints
273
+
274
+ return fdropout.mask_dropout_keypoints(keypoints, dropout_mask)