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,752 @@
1
+ """Geometric transformations for flip and symmetry operations.
2
+
3
+ This module contains transforms that apply various flip and symmetry operations
4
+ to images and other target types. These transforms modify the geometric arrangement
5
+ of the input data while preserving the pixel values themselves.
6
+
7
+ Available transforms:
8
+ - VerticalFlip: Flips the input upside down (around the x-axis)
9
+ - HorizontalFlip: Flips the input left to right (around the y-axis)
10
+ - Transpose: Swaps rows and columns (flips around the main diagonal)
11
+ - D4: Applies one of eight possible square symmetry transformations (dihedral group D4)
12
+ - SquareSymmetry: Alias for D4 with a more intuitive name
13
+
14
+ These transforms are particularly useful for:
15
+ - Data augmentation to improve model generalization
16
+ - Addressing orientation biases in training data
17
+ - Working with data that doesn't have a natural orientation (e.g., satellite imagery)
18
+ - Exploiting symmetries in the problem domain
19
+
20
+ All transforms support various target types including images, masks, bounding boxes,
21
+ keypoints, volumes, and 3D masks, ensuring consistent transformation across
22
+ different data modalities.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ from typing import Any, Literal
28
+
29
+ import numpy as np
30
+ from albucore import hflip, vflip
31
+
32
+ from albumentations.core.transforms_interface import (
33
+ BaseTransformInitSchema,
34
+ DualTransform,
35
+ )
36
+ from albumentations.core.type_definitions import (
37
+ ALL_TARGETS,
38
+ d4_group_elements,
39
+ )
40
+
41
+ from . import functional as fgeometric
42
+
43
+ __all__ = [
44
+ "D4",
45
+ "HorizontalFlip",
46
+ "SquareSymmetry",
47
+ "Transpose",
48
+ "VerticalFlip",
49
+ ]
50
+
51
+
52
+ class VerticalFlip(DualTransform):
53
+ """Flip the input vertically around the x-axis.
54
+
55
+ Args:
56
+ p (float): Probability of applying the transform. Default: 0.5.
57
+
58
+ Targets:
59
+ image, mask, bboxes, keypoints, volume, mask3d
60
+
61
+ Image types:
62
+ uint8, float32
63
+
64
+ Note:
65
+ - This transform flips the image upside down. The top of the image becomes the bottom and vice versa.
66
+ - The dimensions of the image remain unchanged.
67
+ - For multi-channel images (like RGB), each channel is flipped independently.
68
+ - Bounding boxes are adjusted to match their new positions in the flipped image.
69
+ - Keypoints are moved to their new positions in the flipped image.
70
+
71
+ Mathematical Details:
72
+ 1. For an input image I of shape (H, W, C), the output O is:
73
+ O[i, j, k] = I[H-1-i, j, k] for all i in [0, H-1], j in [0, W-1], k in [0, C-1]
74
+ 2. For bounding boxes with coordinates (x_min, y_min, x_max, y_max):
75
+ new_bbox = (x_min, H-y_max, x_max, H-y_min)
76
+ 3. For keypoints with coordinates (x, y):
77
+ new_keypoint = (x, H-y)
78
+ where H is the height of the image.
79
+
80
+ Examples:
81
+ >>> import numpy as np
82
+ >>> import albumentations as A
83
+ >>> image = np.array([
84
+ ... [[1, 2, 3], [4, 5, 6]],
85
+ ... [[7, 8, 9], [10, 11, 12]]
86
+ ... ])
87
+ >>> transform = A.VerticalFlip(p=1.0)
88
+ >>> result = transform(image=image)
89
+ >>> flipped_image = result['image']
90
+ >>> print(flipped_image)
91
+ [[[ 7 8 9]
92
+ [10 11 12]]
93
+ [[ 1 2 3]
94
+ [ 4 5 6]]]
95
+ # The original image is flipped vertically, with rows reversed
96
+
97
+ """
98
+
99
+ _targets = ALL_TARGETS
100
+
101
+ def apply(self, img: np.ndarray, **params: Any) -> np.ndarray:
102
+ """Apply the vertical flip to an image.
103
+
104
+ Args:
105
+ img (np.ndarray): Image to be flipped.
106
+ **params (Any): Additional parameters.
107
+
108
+ Returns:
109
+ np.ndarray: Flipped image.
110
+
111
+ """
112
+ return vflip(img)
113
+
114
+ def apply_to_bboxes(self, bboxes: np.ndarray, **params: Any) -> np.ndarray:
115
+ """Apply the vertical flip to bounding boxes.
116
+
117
+ Args:
118
+ bboxes (np.ndarray): Bounding boxes to be flipped.
119
+ **params (Any): Additional parameters.
120
+
121
+ Returns:
122
+ np.ndarray: Flipped bounding boxes.
123
+
124
+ """
125
+ return fgeometric.bboxes_vflip(bboxes)
126
+
127
+ def apply_to_keypoints(self, keypoints: np.ndarray, **params: Any) -> np.ndarray:
128
+ """Apply the vertical flip to keypoints.
129
+
130
+ Args:
131
+ keypoints (np.ndarray): Keypoints to be flipped.
132
+ **params (Any): Additional parameters.
133
+
134
+ Returns:
135
+ np.ndarray: Flipped keypoints.
136
+
137
+ """
138
+ return fgeometric.keypoints_vflip(keypoints, params["shape"][0])
139
+
140
+ def apply_to_images(self, images: np.ndarray, **params: Any) -> np.ndarray:
141
+ """Apply the vertical flip to a batch of images.
142
+
143
+ Args:
144
+ images (np.ndarray): Images to be flipped.
145
+ **params (Any): Additional parameters.
146
+
147
+ Returns:
148
+ np.ndarray: Flipped images.
149
+
150
+ """
151
+ return fgeometric.volume_vflip(images)
152
+
153
+ def apply_to_volume(self, volume: np.ndarray, **params: Any) -> np.ndarray:
154
+ """Apply the vertical flip to a volume.
155
+
156
+ Args:
157
+ volume (np.ndarray): Volume to be flipped.
158
+ **params (Any): Additional parameters.
159
+
160
+ Returns:
161
+ np.ndarray: Flipped volume.
162
+
163
+ """
164
+ return self.apply_to_images(volume, **params)
165
+
166
+ def apply_to_volumes(self, volumes: np.ndarray, **params: Any) -> np.ndarray:
167
+ """Apply the vertical flip to a batch of volumes.
168
+
169
+ Args:
170
+ volumes (np.ndarray): Volumes to be flipped.
171
+ **params (Any): Additional parameters.
172
+
173
+ Returns:
174
+ np.ndarray: Flipped volumes.
175
+
176
+ """
177
+ return fgeometric.volumes_vflip(volumes)
178
+
179
+ def apply_to_mask3d(self, mask3d: np.ndarray, **params: Any) -> np.ndarray:
180
+ """Apply the vertical flip to a 3D mask.
181
+
182
+ Args:
183
+ mask3d (np.ndarray): 3D mask to be flipped.
184
+ **params (Any): Additional parameters.
185
+
186
+ Returns:
187
+ np.ndarray: Flipped 3D mask.
188
+
189
+ """
190
+ return self.apply_to_images(mask3d, **params)
191
+
192
+ def apply_to_masks3d(self, masks3d: np.ndarray, **params: Any) -> np.ndarray:
193
+ """Apply the vertical flip to a 3D mask.
194
+
195
+ Args:
196
+ masks3d (np.ndarray): 3D masks to be flipped.
197
+ **params (Any): Additional parameters.
198
+
199
+ Returns:
200
+ np.ndarray: Flipped 3D mask.
201
+
202
+ """
203
+ return self.apply_to_volumes(masks3d, **params)
204
+
205
+
206
+ class HorizontalFlip(DualTransform):
207
+ """Flip the input horizontally around the y-axis.
208
+
209
+ Args:
210
+ p (float): probability of applying the transform. Default: 0.5.
211
+
212
+ Targets:
213
+ image, mask, bboxes, keypoints, volume, mask3d
214
+
215
+ Image types:
216
+ uint8, float32
217
+
218
+ Examples:
219
+ >>> import numpy as np
220
+ >>> import albumentations as A
221
+ >>>
222
+ >>> # Prepare sample data
223
+ >>> image = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
224
+ >>> mask = np.array([[1, 0], [0, 1]])
225
+ >>> bboxes = np.array([[0.1, 0.5, 0.3, 0.9]]) # [x_min, y_min, x_max, y_max] format
226
+ >>> keypoints = np.array([[0.1, 0.5], [0.9, 0.5]]) # [x, y] format
227
+ >>>
228
+ >>> # Create a transform with horizontal flip
229
+ >>> transform = A.Compose([
230
+ ... A.HorizontalFlip(p=1.0) # Always apply for this example
231
+ ... ], bbox_params=A.BboxParams(format='yolo', label_fields=[]),
232
+ ... keypoint_params=A.KeypointParams(format='normalized'))
233
+ >>>
234
+ >>> # Apply the transform
235
+ >>> transformed = transform(image=image, mask=mask, bboxes=bboxes, keypoints=keypoints)
236
+ >>>
237
+ >>> # Get the transformed data
238
+ >>> flipped_image = transformed["image"] # Image flipped horizontally
239
+ >>> flipped_mask = transformed["mask"] # Mask flipped horizontally
240
+ >>> flipped_bboxes = transformed["bboxes"] # BBox coordinates adjusted for horizontal flip
241
+ >>> flipped_keypoints = transformed["keypoints"] # Keypoint x-coordinates flipped
242
+
243
+ """
244
+
245
+ _targets = ALL_TARGETS
246
+
247
+ def apply(self, img: np.ndarray, **params: Any) -> np.ndarray:
248
+ """Apply the horizontal flip to an image.
249
+
250
+ Args:
251
+ img (np.ndarray): Image to be flipped.
252
+ **params (Any): Additional parameters.
253
+
254
+ Returns:
255
+ np.ndarray: Flipped image.
256
+
257
+ """
258
+ return hflip(img)
259
+
260
+ def apply_to_bboxes(self, bboxes: np.ndarray, **params: Any) -> np.ndarray:
261
+ """Apply the horizontal flip to bounding boxes.
262
+
263
+ Args:
264
+ bboxes (np.ndarray): Bounding boxes to be flipped.
265
+ **params (Any): Additional parameters.
266
+
267
+ Returns:
268
+ np.ndarray: Flipped bounding boxes.
269
+
270
+ """
271
+ return fgeometric.bboxes_hflip(bboxes)
272
+
273
+ def apply_to_keypoints(self, keypoints: np.ndarray, **params: Any) -> np.ndarray:
274
+ """Apply the horizontal flip to keypoints.
275
+
276
+ Args:
277
+ keypoints (np.ndarray): Keypoints to be flipped.
278
+ **params (Any): Additional parameters.
279
+
280
+ Returns:
281
+ np.ndarray: Flipped keypoints.
282
+
283
+ """
284
+ return fgeometric.keypoints_hflip(keypoints, params["shape"][1])
285
+
286
+ def apply_to_images(self, images: np.ndarray, **params: Any) -> np.ndarray:
287
+ """Apply the horizontal flip to a batch of images.
288
+
289
+ Args:
290
+ images (np.ndarray): Images to be flipped.
291
+ **params (Any): Additional parameters.
292
+
293
+ Returns:
294
+ np.ndarray: Flipped images.
295
+
296
+ """
297
+ return fgeometric.volume_hflip(images)
298
+
299
+ def apply_to_volume(self, volume: np.ndarray, **params: Any) -> np.ndarray:
300
+ """Apply the horizontal flip to a volume.
301
+
302
+ Args:
303
+ volume (np.ndarray): Volume to be flipped.
304
+ **params (Any): Additional parameters.
305
+
306
+ Returns:
307
+ np.ndarray: Flipped volume.
308
+
309
+ """
310
+ return self.apply_to_images(volume, **params)
311
+
312
+ def apply_to_volumes(self, volumes: np.ndarray, **params: Any) -> np.ndarray:
313
+ """Apply the horizontal flip to a batch of volumes.
314
+
315
+ Args:
316
+ volumes (np.ndarray): Volumes to be flipped.
317
+ **params (Any): Additional parameters.
318
+
319
+ Returns:
320
+ np.ndarray: Flipped volumes.
321
+
322
+ """
323
+ return fgeometric.volumes_hflip(volumes)
324
+
325
+ def apply_to_mask3d(self, mask3d: np.ndarray, **params: Any) -> np.ndarray:
326
+ """Apply the horizontal flip to a 3D mask.
327
+
328
+ Args:
329
+ mask3d (np.ndarray): 3D mask to be flipped.
330
+ **params (Any): Additional parameters.
331
+
332
+ """
333
+ return self.apply_to_images(mask3d, **params)
334
+
335
+ def apply_to_masks3d(self, masks3d: np.ndarray, **params: Any) -> np.ndarray:
336
+ """Apply the horizontal flip to a 3D mask.
337
+
338
+ Args:
339
+ masks3d (np.ndarray): 3D masks to be flipped.
340
+ **params (Any): Additional parameters.
341
+
342
+ """
343
+ return self.apply_to_volumes(masks3d, **params)
344
+
345
+
346
+ class Transpose(DualTransform):
347
+ """Transpose the input by swapping its rows and columns.
348
+
349
+ This transform flips the image over its main diagonal, effectively switching its width and height.
350
+ It's equivalent to a 90-degree rotation followed by a horizontal flip.
351
+
352
+ Args:
353
+ p (float): Probability of applying the transform. Default: 0.5.
354
+
355
+ Targets:
356
+ image, mask, bboxes, keypoints, volume, mask3d
357
+
358
+ Image types:
359
+ uint8, float32
360
+
361
+ Note:
362
+ - The dimensions of the output will be swapped compared to the input. For example,
363
+ an input image of shape (100, 200, 3) will result in an output of shape (200, 100, 3).
364
+ - This transform is its own inverse. Applying it twice will return the original input.
365
+ - For multi-channel images (like RGB), the channels are preserved in their original order.
366
+ - Bounding boxes will have their coordinates adjusted to match the new image dimensions.
367
+ - Keypoints will have their x and y coordinates swapped.
368
+
369
+ Mathematical Details:
370
+ 1. For an input image I of shape (H, W, C), the output O is:
371
+ O[i, j, k] = I[j, i, k] for all i in [0, W-1], j in [0, H-1], k in [0, C-1]
372
+ 2. For bounding boxes with coordinates (x_min, y_min, x_max, y_max):
373
+ new_bbox = (y_min, x_min, y_max, x_max)
374
+ 3. For keypoints with coordinates (x, y):
375
+ new_keypoint = (y, x)
376
+
377
+ Examples:
378
+ >>> import numpy as np
379
+ >>> import albumentations as A
380
+ >>> image = np.array([
381
+ ... [[1, 2, 3], [4, 5, 6]],
382
+ ... [[7, 8, 9], [10, 11, 12]]
383
+ ... ])
384
+ >>> transform = A.Transpose(p=1.0)
385
+ >>> result = transform(image=image)
386
+ >>> transposed_image = result['image']
387
+ >>> print(transposed_image)
388
+ [[[ 1 2 3]
389
+ [ 7 8 9]]
390
+ [[ 4 5 6]
391
+ [10 11 12]]]
392
+ # The original 2x2x3 image is now 2x2x3, with rows and columns swapped
393
+
394
+ """
395
+
396
+ _targets = ALL_TARGETS
397
+
398
+ def apply(self, img: np.ndarray, **params: Any) -> np.ndarray:
399
+ """Apply the transpose to an image.
400
+
401
+ Args:
402
+ img (np.ndarray): Image to be transposed.
403
+ **params (Any): Additional parameters.
404
+
405
+ Returns:
406
+ np.ndarray: Transposed image.
407
+
408
+ """
409
+ return fgeometric.transpose(img)
410
+
411
+ def apply_to_bboxes(self, bboxes: np.ndarray, **params: Any) -> np.ndarray:
412
+ """Apply the transpose to bounding boxes.
413
+
414
+ Args:
415
+ bboxes (np.ndarray): Bounding boxes to be transposed.
416
+ **params (Any): Additional parameters.
417
+
418
+ Returns:
419
+ np.ndarray: Transposed bounding boxes.
420
+
421
+ """
422
+ return fgeometric.bboxes_transpose(bboxes)
423
+
424
+ def apply_to_keypoints(self, keypoints: np.ndarray, **params: Any) -> np.ndarray:
425
+ """Apply the transpose to keypoints.
426
+
427
+ Args:
428
+ keypoints (np.ndarray): Keypoints to be transposed.
429
+ **params (Any): Additional parameters.
430
+
431
+ Returns:
432
+ np.ndarray: Transposed keypoints.
433
+
434
+ """
435
+ return fgeometric.keypoints_transpose(keypoints)
436
+
437
+ def apply_to_images(self, images: np.ndarray, **params: Any) -> np.ndarray:
438
+ """Apply the transpose to a batch of images.
439
+
440
+ Args:
441
+ images (np.ndarray): Images to be transposed.
442
+ **params (Any): Additional parameters.
443
+
444
+ Returns:
445
+ np.ndarray: Transposed images.
446
+
447
+ """
448
+ return fgeometric.transpose_images(images)
449
+
450
+ def apply_to_volume(self, volume: np.ndarray, **params: Any) -> np.ndarray:
451
+ """Apply the transpose to a volume.
452
+
453
+ Args:
454
+ volume (np.ndarray): Volume to be transposed.
455
+ **params (Any): Additional parameters.
456
+
457
+ Returns:
458
+ np.ndarray: Transposed volume.
459
+
460
+ """
461
+ return self.apply_to_images(volume, **params)
462
+
463
+ def apply_to_volumes(self, volumes: np.ndarray, **params: Any) -> np.ndarray:
464
+ """Apply the transpose to a batch of volumes.
465
+
466
+ Args:
467
+ volumes (np.ndarray): Volumes to be transposed.
468
+ **params (Any): Additional parameters.
469
+
470
+ Returns:
471
+ np.ndarray: Transposed volumes.
472
+
473
+ """
474
+ return fgeometric.transpose_volumes(volumes)
475
+
476
+ def apply_to_mask3d(self, mask3d: np.ndarray, **params: Any) -> np.ndarray:
477
+ """Apply the transpose to a 3D mask.
478
+
479
+ Args:
480
+ mask3d (np.ndarray): 3D mask to be transposed.
481
+ **params (Any): Additional parameters.
482
+
483
+ Returns:
484
+ np.ndarray: Transposed 3D mask.
485
+
486
+ """
487
+ return self.apply_to_images(mask3d, **params)
488
+
489
+ def apply_to_masks3d(self, masks3d: np.ndarray, **params: Any) -> np.ndarray:
490
+ """Apply the transpose to a batch of 3D masks.
491
+
492
+ Args:
493
+ masks3d (np.ndarray): 3D masks to be transposed.
494
+ **params (Any): Additional parameters.
495
+
496
+ Returns:
497
+ np.ndarray: Transposed 3D masks.
498
+
499
+ """
500
+ return self.apply_to_volumes(masks3d, **params)
501
+
502
+
503
+ class D4(DualTransform):
504
+ """Applies one of the eight possible D4 dihedral group transformations to a square-shaped input,
505
+ maintaining the square shape. These transformations correspond to the symmetries of a square,
506
+ including rotations and reflections.
507
+
508
+ The D4 group transformations include:
509
+ - 'e' (identity): No transformation is applied.
510
+ - 'r90' (rotation by 90 degrees counterclockwise)
511
+ - 'r180' (rotation by 180 degrees)
512
+ - 'r270' (rotation by 270 degrees counterclockwise)
513
+ - 'v' (reflection across the vertical midline)
514
+ - 'hvt' (reflection across the anti-diagonal)
515
+ - 'h' (reflection across the horizontal midline)
516
+ - 't' (reflection across the main diagonal)
517
+
518
+ Even if the probability (`p`) of applying the transform is set to 1, the identity transformation
519
+ 'e' may still occur, which means the input will remain unchanged in one out of eight cases.
520
+
521
+ Args:
522
+ p (float): Probability of applying the transform. Default: 1.0.
523
+
524
+ Targets:
525
+ image, mask, bboxes, keypoints, volume, mask3d
526
+
527
+ Image types:
528
+ uint8, float32
529
+
530
+ Note:
531
+ - This transform is particularly useful for augmenting data that does not have a clear orientation,
532
+ such as top-view satellite or drone imagery, or certain types of medical images.
533
+ - The input image should be square-shaped for optimal results. Non-square inputs may lead to
534
+ unexpected behavior or distortions.
535
+ - When applied to bounding boxes or keypoints, their coordinates will be adjusted according
536
+ to the selected transformation.
537
+ - This transform preserves the aspect ratio and size of the input.
538
+
539
+ Examples:
540
+ >>> import numpy as np
541
+ >>> import albumentations as A
542
+ >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
543
+ >>> transform = A.Compose([
544
+ ... A.D4(p=1.0),
545
+ ... ])
546
+ >>> transformed = transform(image=image)
547
+ >>> transformed_image = transformed['image']
548
+ # The resulting image will be one of the 8 possible D4 transformations of the input
549
+
550
+ """
551
+
552
+ _targets = ALL_TARGETS
553
+
554
+ class InitSchema(BaseTransformInitSchema):
555
+ pass
556
+
557
+ def __init__(
558
+ self,
559
+ p: float = 1,
560
+ ):
561
+ super().__init__(p=p)
562
+
563
+ def apply(
564
+ self,
565
+ img: np.ndarray,
566
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
567
+ **params: Any,
568
+ ) -> np.ndarray:
569
+ """Apply the D4 transform to an image.
570
+
571
+ Args:
572
+ img (np.ndarray): Image to be transformed.
573
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
574
+ **params (Any): Additional parameters.
575
+
576
+ Returns:
577
+ np.ndarray: Transformed image.
578
+
579
+ """
580
+ return fgeometric.d4(img, group_element)
581
+
582
+ def apply_to_bboxes(
583
+ self,
584
+ bboxes: np.ndarray,
585
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
586
+ **params: Any,
587
+ ) -> np.ndarray:
588
+ """Apply the D4 transform to bounding boxes.
589
+
590
+ Args:
591
+ bboxes (np.ndarray): Bounding boxes to be transformed.
592
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
593
+ **params (Any): Additional parameters.
594
+
595
+ Returns:
596
+ np.ndarray: Transformed bounding boxes.
597
+
598
+ """
599
+ return fgeometric.bboxes_d4(bboxes, group_element)
600
+
601
+ def apply_to_keypoints(
602
+ self,
603
+ keypoints: np.ndarray,
604
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
605
+ **params: Any,
606
+ ) -> np.ndarray:
607
+ """Apply the D4 transform to keypoints.
608
+
609
+ Args:
610
+ keypoints (np.ndarray): Keypoints to be transformed.
611
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
612
+ **params (Any): Additional parameters.
613
+
614
+ """
615
+ return fgeometric.keypoints_d4(keypoints, group_element, params["shape"])
616
+
617
+ def apply_to_images(
618
+ self,
619
+ images: np.ndarray,
620
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
621
+ **params: Any,
622
+ ) -> np.ndarray:
623
+ """Apply the D4 transform to a batch of images.
624
+
625
+ Args:
626
+ images (np.ndarray): Images to be transformed.
627
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
628
+ **params (Any): Additional parameters.
629
+
630
+ """
631
+ return fgeometric.d4_images(images, group_element)
632
+
633
+ def apply_to_volume(
634
+ self,
635
+ volume: np.ndarray,
636
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
637
+ **params: Any,
638
+ ) -> np.ndarray:
639
+ """Apply the D4 transform to a volume.
640
+
641
+ Args:
642
+ volume (np.ndarray): Volume to be transformed.
643
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
644
+ **params (Any): Additional parameters.
645
+
646
+ """
647
+ return self.apply_to_images(volume, group_element, **params)
648
+
649
+ def apply_to_volumes(
650
+ self,
651
+ volumes: np.ndarray,
652
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
653
+ **params: Any,
654
+ ) -> np.ndarray:
655
+ """Apply the D4 transform to a batch of volumes.
656
+
657
+ Args:
658
+ volumes (np.ndarray): Volumes to be transformed.
659
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
660
+ **params (Any): Additional parameters.
661
+
662
+ """
663
+ return fgeometric.d4_images(volumes, group_element)
664
+
665
+ def apply_to_mask3d(
666
+ self,
667
+ mask3d: np.ndarray,
668
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
669
+ **params: Any,
670
+ ) -> np.ndarray:
671
+ """Apply the D4 transform to a 3D mask.
672
+
673
+ Args:
674
+ mask3d (np.ndarray): 3D mask to be transformed.
675
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
676
+ **params (Any): Additional parameters.
677
+
678
+ """
679
+ return self.apply_to_images(mask3d, group_element, **params)
680
+
681
+ def apply_to_masks3d(
682
+ self,
683
+ masks3d: np.ndarray,
684
+ group_element: Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"],
685
+ **params: Any,
686
+ ) -> np.ndarray:
687
+ """Apply the D4 transform to a batch of 3D masks.
688
+
689
+ Args:
690
+ masks3d (np.ndarray): 3D masks to be transformed.
691
+ group_element (Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]): Group element to apply.
692
+ **params (Any): Additional parameters.
693
+
694
+ """
695
+ return self.apply_to_volumes(masks3d, group_element, **params)
696
+
697
+ def get_params(self) -> dict[str, Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]]:
698
+ """Get the parameters for the D4 transform.
699
+
700
+ Returns:
701
+ dict[str, Literal["e", "r90", "r180", "r270", "v", "hvt", "h", "t"]]: Parameters.
702
+
703
+ """
704
+ return {
705
+ "group_element": self.random_generator.choice(d4_group_elements),
706
+ }
707
+
708
+
709
+ class SquareSymmetry(D4):
710
+ """Applies one of the eight possible square symmetry transformations to a square-shaped input.
711
+ This is an alias for D4 transform with a more intuitive name for those not familiar with group theory.
712
+
713
+ The square symmetry transformations include:
714
+ - Identity: No transformation is applied
715
+ - 90° rotation: Rotate 90 degrees counterclockwise
716
+ - 180° rotation: Rotate 180 degrees
717
+ - 270° rotation: Rotate 270 degrees counterclockwise
718
+ - Vertical flip: Mirror across vertical axis
719
+ - Anti-diagonal flip: Mirror across anti-diagonal
720
+ - Horizontal flip: Mirror across horizontal axis
721
+ - Main diagonal flip: Mirror across main diagonal
722
+
723
+ Args:
724
+ p (float): Probability of applying the transform. Default: 1.0.
725
+
726
+ Targets:
727
+ image, mask, bboxes, keypoints, volume, mask3d
728
+
729
+ Image types:
730
+ uint8, float32
731
+
732
+ Note:
733
+ - This transform is particularly useful for augmenting data that does not have a clear orientation,
734
+ such as top-view satellite or drone imagery, or certain types of medical images.
735
+ - The input image should be square-shaped for optimal results. Non-square inputs may lead to
736
+ unexpected behavior or distortions.
737
+ - When applied to bounding boxes or keypoints, their coordinates will be adjusted according
738
+ to the selected transformation.
739
+ - This transform preserves the aspect ratio and size of the input.
740
+
741
+ Examples:
742
+ >>> import numpy as np
743
+ >>> import albumentations as A
744
+ >>> image = np.random.randint(0, 256, (100, 100, 3), dtype=np.uint8)
745
+ >>> transform = A.Compose([
746
+ ... A.SquareSymmetry(p=1.0),
747
+ ... ])
748
+ >>> transformed = transform(image=image)
749
+ >>> transformed_image = transformed['image']
750
+ # The resulting image will be one of the 8 possible square symmetry transformations of the input
751
+
752
+ """