stouputils 1.14.0__py3-none-any.whl → 1.14.2__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.
Files changed (108) hide show
  1. stouputils/__init__.pyi +15 -0
  2. stouputils/_deprecated.pyi +12 -0
  3. stouputils/all_doctests.pyi +46 -0
  4. stouputils/applications/__init__.pyi +2 -0
  5. stouputils/applications/automatic_docs.py +3 -0
  6. stouputils/applications/automatic_docs.pyi +106 -0
  7. stouputils/applications/upscaler/__init__.pyi +3 -0
  8. stouputils/applications/upscaler/config.pyi +18 -0
  9. stouputils/applications/upscaler/image.pyi +109 -0
  10. stouputils/applications/upscaler/video.pyi +60 -0
  11. stouputils/archive.pyi +67 -0
  12. stouputils/backup.pyi +109 -0
  13. stouputils/collections.pyi +86 -0
  14. stouputils/continuous_delivery/__init__.pyi +5 -0
  15. stouputils/continuous_delivery/cd_utils.pyi +129 -0
  16. stouputils/continuous_delivery/github.pyi +162 -0
  17. stouputils/continuous_delivery/pypi.pyi +52 -0
  18. stouputils/continuous_delivery/pyproject.pyi +67 -0
  19. stouputils/continuous_delivery/stubs.pyi +39 -0
  20. stouputils/ctx.pyi +211 -0
  21. stouputils/data_science/config/get.py +51 -51
  22. stouputils/data_science/data_processing/image/__init__.py +66 -66
  23. stouputils/data_science/data_processing/image/auto_contrast.py +79 -79
  24. stouputils/data_science/data_processing/image/axis_flip.py +58 -58
  25. stouputils/data_science/data_processing/image/bias_field_correction.py +74 -74
  26. stouputils/data_science/data_processing/image/binary_threshold.py +73 -73
  27. stouputils/data_science/data_processing/image/blur.py +59 -59
  28. stouputils/data_science/data_processing/image/brightness.py +54 -54
  29. stouputils/data_science/data_processing/image/canny.py +110 -110
  30. stouputils/data_science/data_processing/image/clahe.py +92 -92
  31. stouputils/data_science/data_processing/image/common.py +30 -30
  32. stouputils/data_science/data_processing/image/contrast.py +53 -53
  33. stouputils/data_science/data_processing/image/curvature_flow_filter.py +74 -74
  34. stouputils/data_science/data_processing/image/denoise.py +378 -378
  35. stouputils/data_science/data_processing/image/histogram_equalization.py +123 -123
  36. stouputils/data_science/data_processing/image/invert.py +64 -64
  37. stouputils/data_science/data_processing/image/laplacian.py +60 -60
  38. stouputils/data_science/data_processing/image/median_blur.py +52 -52
  39. stouputils/data_science/data_processing/image/noise.py +59 -59
  40. stouputils/data_science/data_processing/image/normalize.py +65 -65
  41. stouputils/data_science/data_processing/image/random_erase.py +66 -66
  42. stouputils/data_science/data_processing/image/resize.py +69 -69
  43. stouputils/data_science/data_processing/image/rotation.py +80 -80
  44. stouputils/data_science/data_processing/image/salt_pepper.py +68 -68
  45. stouputils/data_science/data_processing/image/sharpening.py +55 -55
  46. stouputils/data_science/data_processing/image/shearing.py +64 -64
  47. stouputils/data_science/data_processing/image/threshold.py +64 -64
  48. stouputils/data_science/data_processing/image/translation.py +71 -71
  49. stouputils/data_science/data_processing/image/zoom.py +83 -83
  50. stouputils/data_science/data_processing/image_augmentation.py +118 -118
  51. stouputils/data_science/data_processing/image_preprocess.py +183 -183
  52. stouputils/data_science/data_processing/prosthesis_detection.py +359 -359
  53. stouputils/data_science/data_processing/technique.py +481 -481
  54. stouputils/data_science/dataset/__init__.py +45 -45
  55. stouputils/data_science/dataset/dataset.py +292 -292
  56. stouputils/data_science/dataset/dataset_loader.py +135 -135
  57. stouputils/data_science/dataset/grouping_strategy.py +296 -296
  58. stouputils/data_science/dataset/image_loader.py +100 -100
  59. stouputils/data_science/dataset/xy_tuple.py +696 -696
  60. stouputils/data_science/metric_dictionnary.py +106 -106
  61. stouputils/data_science/mlflow_utils.py +206 -206
  62. stouputils/data_science/models/abstract_model.py +149 -149
  63. stouputils/data_science/models/all.py +85 -85
  64. stouputils/data_science/models/keras/all.py +38 -38
  65. stouputils/data_science/models/keras/convnext.py +62 -62
  66. stouputils/data_science/models/keras/densenet.py +50 -50
  67. stouputils/data_science/models/keras/efficientnet.py +60 -60
  68. stouputils/data_science/models/keras/mobilenet.py +56 -56
  69. stouputils/data_science/models/keras/resnet.py +52 -52
  70. stouputils/data_science/models/keras/squeezenet.py +233 -233
  71. stouputils/data_science/models/keras/vgg.py +42 -42
  72. stouputils/data_science/models/keras/xception.py +38 -38
  73. stouputils/data_science/models/keras_utils/callbacks/__init__.py +20 -20
  74. stouputils/data_science/models/keras_utils/callbacks/colored_progress_bar.py +219 -219
  75. stouputils/data_science/models/keras_utils/callbacks/learning_rate_finder.py +148 -148
  76. stouputils/data_science/models/keras_utils/callbacks/model_checkpoint_v2.py +31 -31
  77. stouputils/data_science/models/keras_utils/callbacks/progressive_unfreezing.py +249 -249
  78. stouputils/data_science/models/keras_utils/callbacks/warmup_scheduler.py +66 -66
  79. stouputils/data_science/models/keras_utils/losses/__init__.py +12 -12
  80. stouputils/data_science/models/keras_utils/losses/next_generation_loss.py +56 -56
  81. stouputils/data_science/models/keras_utils/visualizations.py +416 -416
  82. stouputils/data_science/models/sandbox.py +116 -116
  83. stouputils/data_science/range_tuple.py +234 -234
  84. stouputils/data_science/utils.py +285 -285
  85. stouputils/decorators.pyi +242 -0
  86. stouputils/image.pyi +172 -0
  87. stouputils/installer/__init__.py +18 -18
  88. stouputils/installer/__init__.pyi +5 -0
  89. stouputils/installer/common.pyi +39 -0
  90. stouputils/installer/downloader.pyi +24 -0
  91. stouputils/installer/linux.py +144 -144
  92. stouputils/installer/linux.pyi +39 -0
  93. stouputils/installer/main.py +223 -223
  94. stouputils/installer/main.pyi +57 -0
  95. stouputils/installer/windows.py +136 -136
  96. stouputils/installer/windows.pyi +31 -0
  97. stouputils/io.pyi +213 -0
  98. stouputils/parallel.py +12 -10
  99. stouputils/parallel.pyi +211 -0
  100. stouputils/print.pyi +136 -0
  101. stouputils/py.typed +1 -1
  102. stouputils/stouputils/parallel.pyi +4 -4
  103. stouputils/version_pkg.pyi +15 -0
  104. {stouputils-1.14.0.dist-info → stouputils-1.14.2.dist-info}/METADATA +1 -1
  105. stouputils-1.14.2.dist-info/RECORD +171 -0
  106. stouputils-1.14.0.dist-info/RECORD +0 -140
  107. {stouputils-1.14.0.dist-info → stouputils-1.14.2.dist-info}/WHEEL +0 -0
  108. {stouputils-1.14.0.dist-info → stouputils-1.14.2.dist-info}/entry_points.txt +0 -0
@@ -1,51 +1,51 @@
1
- """ Load configuration from the set.py file and handle some special cases.
2
-
3
- Proper way to get the configuration is by importing this module, not the set.py file directly.
4
- """
5
-
6
- # pyright: reportUnknownMemberType=false
7
- # pyright: reportUnknownVariableType=false
8
- # pyright: reportMissingTypeStubs=false
9
-
10
- # Imports
11
- import os
12
- from typing import Any
13
-
14
- from .set import DataScienceConfig
15
-
16
- # Special cases
17
- # Hide GPU when using CPU
18
- if DataScienceConfig.TENSORFLOW_DEVICE.lower().startswith("/cpu"):
19
- os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
20
-
21
- # Precise which GPU we use
22
- elif DataScienceConfig.TENSORFLOW_DEVICE.lower().startswith("/gpu"):
23
- os.environ["CUDA_VISIBLE_DEVICES"] = DataScienceConfig.TENSORFLOW_DEVICE.split(":")[-1]
24
-
25
- # Configure TensorFlow (if available)
26
- try:
27
- from tensorflow import config as tf_config
28
-
29
- # Get the physical devices
30
- physical_devices: list[Any] = tf_config.list_physical_devices("GPU")
31
-
32
- # Configure TensorFlow GPU memory management to allocate memory dynamically
33
- # This prevents TensorFlow from allocating all GPU memory upfront
34
- # Instead, memory will grow as needed, allowing better resource sharing
35
- for device in physical_devices:
36
- tf_config.experimental.set_memory_growth(device, True)
37
-
38
- # Disable eager execution mode in TensorFlow
39
- # This improves performance by allowing TensorFlow to create an optimized graph
40
- # of operations instead of executing operations one by one (at the cost of debugging difficulty)
41
- tf_config.run_functions_eagerly(False)
42
- except ImportError:
43
- pass
44
-
45
- # Enable mixed precision training (if available)
46
- try:
47
- from keras import mixed_precision
48
- mixed_precision.set_global_policy(DataScienceConfig.MIXED_PRECISION_POLICY)
49
- except ImportError:
50
- pass
51
-
1
+ """ Load configuration from the set.py file and handle some special cases.
2
+
3
+ Proper way to get the configuration is by importing this module, not the set.py file directly.
4
+ """
5
+
6
+ # pyright: reportUnknownMemberType=false
7
+ # pyright: reportUnknownVariableType=false
8
+ # pyright: reportMissingTypeStubs=false
9
+
10
+ # Imports
11
+ import os
12
+ from typing import Any
13
+
14
+ from .set import DataScienceConfig
15
+
16
+ # Special cases
17
+ # Hide GPU when using CPU
18
+ if DataScienceConfig.TENSORFLOW_DEVICE.lower().startswith("/cpu"):
19
+ os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
20
+
21
+ # Precise which GPU we use
22
+ elif DataScienceConfig.TENSORFLOW_DEVICE.lower().startswith("/gpu"):
23
+ os.environ["CUDA_VISIBLE_DEVICES"] = DataScienceConfig.TENSORFLOW_DEVICE.split(":")[-1]
24
+
25
+ # Configure TensorFlow (if available)
26
+ try:
27
+ from tensorflow import config as tf_config
28
+
29
+ # Get the physical devices
30
+ physical_devices: list[Any] = tf_config.list_physical_devices("GPU")
31
+
32
+ # Configure TensorFlow GPU memory management to allocate memory dynamically
33
+ # This prevents TensorFlow from allocating all GPU memory upfront
34
+ # Instead, memory will grow as needed, allowing better resource sharing
35
+ for device in physical_devices:
36
+ tf_config.experimental.set_memory_growth(device, True)
37
+
38
+ # Disable eager execution mode in TensorFlow
39
+ # This improves performance by allowing TensorFlow to create an optimized graph
40
+ # of operations instead of executing operations one by one (at the cost of debugging difficulty)
41
+ tf_config.run_functions_eagerly(False)
42
+ except ImportError:
43
+ pass
44
+
45
+ # Enable mixed precision training (if available)
46
+ try:
47
+ from keras import mixed_precision
48
+ mixed_precision.set_global_policy(DataScienceConfig.MIXED_PRECISION_POLICY)
49
+ except ImportError:
50
+ pass
51
+
@@ -1,66 +1,66 @@
1
-
2
- # Imports
3
- from .auto_contrast import auto_contrast_image
4
- from .axis_flip import flip_image
5
- from .bias_field_correction import bias_field_correction_image
6
- from .binary_threshold import binary_threshold_image
7
- from .blur import blur_image
8
- from .brightness import brightness_image
9
- from .canny import canny_image
10
- from .clahe import clahe_image
11
- from .contrast import contrast_image
12
- from .curvature_flow_filter import curvature_flow_filter_image
13
- from .denoise import (
14
- adaptive_denoise_image,
15
- bilateral_denoise_image,
16
- nlm_denoise_image,
17
- tv_denoise_image,
18
- wavelet_denoise_image,
19
- )
20
- from .invert import invert_image
21
- from .laplacian import laplacian_image
22
- from .median_blur import median_blur_image
23
- from .noise import noise_image
24
- from .normalize import normalize_image
25
- from .random_erase import random_erase_image
26
- from .resize import resize_image
27
- from .rotation import rotate_image
28
- from .salt_pepper import salt_pepper_image
29
- from .sharpening import sharpen_image
30
- from .shearing import shear_image
31
- from .threshold import threshold_image
32
- from .translation import translate_image
33
- from .zoom import zoom_image
34
-
35
- __all__ = [
36
- "adaptive_denoise_image",
37
- "auto_contrast_image",
38
- "bias_field_correction_image",
39
- "bilateral_denoise_image",
40
- "binary_threshold_image",
41
- "blur_image",
42
- "brightness_image",
43
- "canny_image",
44
- "clahe_image",
45
- "contrast_image",
46
- "curvature_flow_filter_image",
47
- "flip_image",
48
- "invert_image",
49
- "laplacian_image",
50
- "median_blur_image",
51
- "nlm_denoise_image",
52
- "noise_image",
53
- "normalize_image",
54
- "random_erase_image",
55
- "resize_image",
56
- "rotate_image",
57
- "salt_pepper_image",
58
- "sharpen_image",
59
- "shear_image",
60
- "threshold_image",
61
- "translate_image",
62
- "tv_denoise_image",
63
- "wavelet_denoise_image",
64
- "zoom_image",
65
- ]
66
-
1
+
2
+ # Imports
3
+ from .auto_contrast import auto_contrast_image
4
+ from .axis_flip import flip_image
5
+ from .bias_field_correction import bias_field_correction_image
6
+ from .binary_threshold import binary_threshold_image
7
+ from .blur import blur_image
8
+ from .brightness import brightness_image
9
+ from .canny import canny_image
10
+ from .clahe import clahe_image
11
+ from .contrast import contrast_image
12
+ from .curvature_flow_filter import curvature_flow_filter_image
13
+ from .denoise import (
14
+ adaptive_denoise_image,
15
+ bilateral_denoise_image,
16
+ nlm_denoise_image,
17
+ tv_denoise_image,
18
+ wavelet_denoise_image,
19
+ )
20
+ from .invert import invert_image
21
+ from .laplacian import laplacian_image
22
+ from .median_blur import median_blur_image
23
+ from .noise import noise_image
24
+ from .normalize import normalize_image
25
+ from .random_erase import random_erase_image
26
+ from .resize import resize_image
27
+ from .rotation import rotate_image
28
+ from .salt_pepper import salt_pepper_image
29
+ from .sharpening import sharpen_image
30
+ from .shearing import shear_image
31
+ from .threshold import threshold_image
32
+ from .translation import translate_image
33
+ from .zoom import zoom_image
34
+
35
+ __all__ = [
36
+ "adaptive_denoise_image",
37
+ "auto_contrast_image",
38
+ "bias_field_correction_image",
39
+ "bilateral_denoise_image",
40
+ "binary_threshold_image",
41
+ "blur_image",
42
+ "brightness_image",
43
+ "canny_image",
44
+ "clahe_image",
45
+ "contrast_image",
46
+ "curvature_flow_filter_image",
47
+ "flip_image",
48
+ "invert_image",
49
+ "laplacian_image",
50
+ "median_blur_image",
51
+ "nlm_denoise_image",
52
+ "noise_image",
53
+ "normalize_image",
54
+ "random_erase_image",
55
+ "resize_image",
56
+ "rotate_image",
57
+ "salt_pepper_image",
58
+ "sharpen_image",
59
+ "shear_image",
60
+ "threshold_image",
61
+ "translate_image",
62
+ "tv_denoise_image",
63
+ "wavelet_denoise_image",
64
+ "zoom_image",
65
+ ]
66
+
@@ -1,79 +1,79 @@
1
-
2
- # pyright: reportUnusedImport=false
3
- # ruff: noqa: F401
4
-
5
- # Imports
6
- from .common import Any, NDArray, check_image, cv2, np
7
-
8
-
9
- # Functions
10
- def auto_contrast_image(image: NDArray[Any], ignore_dtype: bool = False) -> NDArray[Any]:
11
- """ Adjust the contrast of an image.
12
-
13
- Args:
14
- image (NDArray[Any]): Image to adjust contrast
15
- ignore_dtype (bool): Ignore the dtype check
16
- Returns:
17
- NDArray[Any]: Image with adjusted contrast
18
-
19
- >>> ## Basic tests
20
- >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8)
21
- >>> adjusted = auto_contrast_image(image)
22
- >>> adjusted.tolist()
23
- [[0, 36, 73], [109, 146, 182], [219, 255, 255]]
24
- >>> adjusted.shape == image.shape
25
- True
26
- >>> adjusted.dtype == image.dtype
27
- True
28
-
29
- >>> ## Test invalid inputs
30
- >>> auto_contrast_image("not an image")
31
- Traceback (most recent call last):
32
- ...
33
- AssertionError: Image must be a numpy array
34
- """
35
- # Check input data
36
- check_image(image, ignore_dtype=ignore_dtype)
37
-
38
- # Perform histogram clipping
39
- clip_hist_percent: float = 1.0
40
-
41
- # Calculate the histogram of the image
42
- hist: NDArray[Any] = cv2.calcHist([image], [0], None, [256], [0, 256])
43
-
44
- # Create an accumulator list to store the cumulative histogram
45
- accumulator: list[float] = []
46
- accumulator.append(hist[0])
47
- for i in range(1, 256):
48
- accumulator.append(accumulator[i - 1] + hist[i])
49
-
50
- # Find the maximum value in the accumulator
51
- max_value: float = accumulator[-1]
52
-
53
- # Calculate the clipping threshold
54
- clip_hist_percent = clip_hist_percent * (max_value / 100.0)
55
- clip_hist_percent = clip_hist_percent / 2.0
56
-
57
- # Find the minimum and maximum gray levels after clipping
58
- min_gray: int = 0
59
- while accumulator[min_gray] < clip_hist_percent:
60
- min_gray = min_gray + 1
61
- max_gray: int = 256 - 1
62
- while (max_gray >= 0 and accumulator[max_gray] >= (max_value - clip_hist_percent)):
63
- max_gray = max_gray - 1
64
-
65
- # Calculate the input range after clipping
66
- input_range: int = max_gray - min_gray
67
-
68
- # If the input range is 0, return the original image
69
- if input_range == 0:
70
- return image
71
-
72
- # Calculate the scaling factors for contrast adjustment
73
- alpha: float = (256 - 1) / input_range
74
- beta: float = -min_gray * alpha
75
-
76
- # Apply the contrast adjustment
77
- adjusted: NDArray[Any] = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
78
- return adjusted
79
-
1
+
2
+ # pyright: reportUnusedImport=false
3
+ # ruff: noqa: F401
4
+
5
+ # Imports
6
+ from .common import Any, NDArray, check_image, cv2, np
7
+
8
+
9
+ # Functions
10
+ def auto_contrast_image(image: NDArray[Any], ignore_dtype: bool = False) -> NDArray[Any]:
11
+ """ Adjust the contrast of an image.
12
+
13
+ Args:
14
+ image (NDArray[Any]): Image to adjust contrast
15
+ ignore_dtype (bool): Ignore the dtype check
16
+ Returns:
17
+ NDArray[Any]: Image with adjusted contrast
18
+
19
+ >>> ## Basic tests
20
+ >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8)
21
+ >>> adjusted = auto_contrast_image(image)
22
+ >>> adjusted.tolist()
23
+ [[0, 36, 73], [109, 146, 182], [219, 255, 255]]
24
+ >>> adjusted.shape == image.shape
25
+ True
26
+ >>> adjusted.dtype == image.dtype
27
+ True
28
+
29
+ >>> ## Test invalid inputs
30
+ >>> auto_contrast_image("not an image")
31
+ Traceback (most recent call last):
32
+ ...
33
+ AssertionError: Image must be a numpy array
34
+ """
35
+ # Check input data
36
+ check_image(image, ignore_dtype=ignore_dtype)
37
+
38
+ # Perform histogram clipping
39
+ clip_hist_percent: float = 1.0
40
+
41
+ # Calculate the histogram of the image
42
+ hist: NDArray[Any] = cv2.calcHist([image], [0], None, [256], [0, 256])
43
+
44
+ # Create an accumulator list to store the cumulative histogram
45
+ accumulator: list[float] = []
46
+ accumulator.append(hist[0])
47
+ for i in range(1, 256):
48
+ accumulator.append(accumulator[i - 1] + hist[i])
49
+
50
+ # Find the maximum value in the accumulator
51
+ max_value: float = accumulator[-1]
52
+
53
+ # Calculate the clipping threshold
54
+ clip_hist_percent = clip_hist_percent * (max_value / 100.0)
55
+ clip_hist_percent = clip_hist_percent / 2.0
56
+
57
+ # Find the minimum and maximum gray levels after clipping
58
+ min_gray: int = 0
59
+ while accumulator[min_gray] < clip_hist_percent:
60
+ min_gray = min_gray + 1
61
+ max_gray: int = 256 - 1
62
+ while (max_gray >= 0 and accumulator[max_gray] >= (max_value - clip_hist_percent)):
63
+ max_gray = max_gray - 1
64
+
65
+ # Calculate the input range after clipping
66
+ input_range: int = max_gray - min_gray
67
+
68
+ # If the input range is 0, return the original image
69
+ if input_range == 0:
70
+ return image
71
+
72
+ # Calculate the scaling factors for contrast adjustment
73
+ alpha: float = (256 - 1) / input_range
74
+ beta: float = -min_gray * alpha
75
+
76
+ # Apply the contrast adjustment
77
+ adjusted: NDArray[Any] = cv2.convertScaleAbs(image, alpha=alpha, beta=beta)
78
+ return adjusted
79
+
@@ -1,58 +1,58 @@
1
-
2
- # pyright: reportUnusedImport=false
3
- # ruff: noqa: F401
4
-
5
- # Imports
6
- from typing import Literal
7
-
8
- from .common import Any, NDArray, check_image, cv2, np
9
-
10
-
11
- # Functions
12
- def flip_image(
13
- image: NDArray[Any], axis: Literal["horizontal", "vertical", "both"], ignore_dtype: bool = True
14
- ) -> NDArray[Any]:
15
- """ Flip an image along specified axis
16
-
17
- Args:
18
- image (NDArray[Any]): Image to flip
19
- axis (str): Axis along which to flip ("horizontal" or "vertical" or "both")
20
- ignore_dtype (bool): Ignore the dtype check
21
- Returns:
22
- NDArray[Any]: Flipped image
23
-
24
- >>> ## Basic tests
25
- >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
26
- >>> flip_image(image, "horizontal").tolist()
27
- [[3, 2, 1], [6, 5, 4], [9, 8, 7]]
28
-
29
- >>> flip_image(image, "vertical").tolist()
30
- [[7, 8, 9], [4, 5, 6], [1, 2, 3]]
31
-
32
- >>> flip_image(image, "both").tolist()
33
- [[9, 8, 7], [6, 5, 4], [3, 2, 1]]
34
-
35
- >>> ## Test invalid inputs
36
- >>> flip_image(image, "diagonal")
37
- Traceback (most recent call last):
38
- AssertionError: axis must be either 'horizontal' or 'vertical' or 'both', got 'diagonal'
39
-
40
- >>> flip_image("not an image", "horizontal")
41
- Traceback (most recent call last):
42
- ...
43
- AssertionError: Image must be a numpy array
44
- """
45
- # Check input data
46
- check_image(image, ignore_dtype=ignore_dtype)
47
- assert axis in ("horizontal", "vertical", "both"), (
48
- f"axis must be either 'horizontal' or 'vertical' or 'both', got '{axis}'"
49
- )
50
-
51
- # Apply the flip
52
- if axis == "horizontal":
53
- return cv2.flip(image, 1) # 1 for horizontal flip
54
- elif axis == "vertical":
55
- return cv2.flip(image, 0) # 0 for vertical flip
56
- else:
57
- return cv2.flip(image, -1) # -1 for both flips
58
-
1
+
2
+ # pyright: reportUnusedImport=false
3
+ # ruff: noqa: F401
4
+
5
+ # Imports
6
+ from typing import Literal
7
+
8
+ from .common import Any, NDArray, check_image, cv2, np
9
+
10
+
11
+ # Functions
12
+ def flip_image(
13
+ image: NDArray[Any], axis: Literal["horizontal", "vertical", "both"], ignore_dtype: bool = True
14
+ ) -> NDArray[Any]:
15
+ """ Flip an image along specified axis
16
+
17
+ Args:
18
+ image (NDArray[Any]): Image to flip
19
+ axis (str): Axis along which to flip ("horizontal" or "vertical" or "both")
20
+ ignore_dtype (bool): Ignore the dtype check
21
+ Returns:
22
+ NDArray[Any]: Flipped image
23
+
24
+ >>> ## Basic tests
25
+ >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
26
+ >>> flip_image(image, "horizontal").tolist()
27
+ [[3, 2, 1], [6, 5, 4], [9, 8, 7]]
28
+
29
+ >>> flip_image(image, "vertical").tolist()
30
+ [[7, 8, 9], [4, 5, 6], [1, 2, 3]]
31
+
32
+ >>> flip_image(image, "both").tolist()
33
+ [[9, 8, 7], [6, 5, 4], [3, 2, 1]]
34
+
35
+ >>> ## Test invalid inputs
36
+ >>> flip_image(image, "diagonal")
37
+ Traceback (most recent call last):
38
+ AssertionError: axis must be either 'horizontal' or 'vertical' or 'both', got 'diagonal'
39
+
40
+ >>> flip_image("not an image", "horizontal")
41
+ Traceback (most recent call last):
42
+ ...
43
+ AssertionError: Image must be a numpy array
44
+ """
45
+ # Check input data
46
+ check_image(image, ignore_dtype=ignore_dtype)
47
+ assert axis in ("horizontal", "vertical", "both"), (
48
+ f"axis must be either 'horizontal' or 'vertical' or 'both', got '{axis}'"
49
+ )
50
+
51
+ # Apply the flip
52
+ if axis == "horizontal":
53
+ return cv2.flip(image, 1) # 1 for horizontal flip
54
+ elif axis == "vertical":
55
+ return cv2.flip(image, 0) # 0 for vertical flip
56
+ else:
57
+ return cv2.flip(image, -1) # -1 for both flips
58
+
@@ -1,74 +1,74 @@
1
-
2
- # pyright: reportUnknownMemberType=false
3
- # pyright: reportUnknownArgumentType=false
4
- # pyright: reportUnknownVariableType=false
5
-
6
- # Imports
7
- import SimpleITK as Sitk
8
-
9
- from .common import Any, NDArray, check_image, np
10
-
11
-
12
- # Functions
13
- def bias_field_correction_image(image: NDArray[Any], ignore_dtype: bool = False) -> NDArray[Any]:
14
- """ Apply a bias field correction to an image. (N4 Filter)
15
-
16
- Args:
17
- image (NDArray[Any]): Image to apply the bias field correction (can't be 8-bit unsigned integer)
18
- ignore_dtype (bool): Ignore the dtype check
19
- Returns:
20
- NDArray[Any]: Image with the curvature flow filter applied
21
-
22
- >>> ## Basic tests
23
- >>> image = np.random.randint(0, 255, size=(10,10), dtype=np.uint8) / 255
24
- >>> corrected = bias_field_correction_image(image)
25
- >>> corrected.shape == image.shape
26
- True
27
- >>> corrected.dtype == np.float64
28
- True
29
-
30
- >>> ## Test invalid inputs
31
- >>> bias_field_correction_image("not an image")
32
- Traceback (most recent call last):
33
- ...
34
- AssertionError: Image must be a numpy array
35
- """
36
- # Check input data
37
- check_image(image, ignore_dtype=ignore_dtype)
38
-
39
- # If the image is 3D, convert to grayscale first
40
- if image.ndim == 3:
41
- image = np.mean(image, axis=-1)
42
-
43
- # Convert numpy array to SimpleITK image
44
- image_sitk: Sitk.Image = Sitk.GetImageFromArray(image)
45
-
46
- # Create binary mask of the head region
47
- transformed: Sitk.Image = Sitk.RescaleIntensity(image_sitk) # Normalize intensities
48
- transformed = Sitk.LiThreshold(transformed, 0, 1) # Apply Li thresholding
49
- head_mask: Sitk.Image = transformed
50
-
51
- # Downsample images to speed up bias field estimation
52
- shrink_factor: int = 4 # Reduce image size by factor of 4
53
- input_image: Sitk.Image = Sitk.Shrink(
54
- image_sitk,
55
- [shrink_factor] * image_sitk.GetDimension() # Apply shrink factor to all dimensions
56
- )
57
- mask_image: Sitk.Image = Sitk.Shrink(
58
- head_mask,
59
- [shrink_factor] * image_sitk.GetDimension()
60
- )
61
-
62
- # Apply N4 bias field correction
63
- corrector = Sitk.N4BiasFieldCorrectionImageFilter()
64
- corrector.Execute(input_image, mask_image)
65
-
66
- # Get estimated bias field and apply correction
67
- log_bias_field: Sitk.Image = Sitk.Cast(
68
- corrector.GetLogBiasFieldAsImage(image_sitk), Sitk.sitkFloat64
69
- )
70
- corrected_image_full_resolution: Sitk.Image = image_sitk / Sitk.Exp(log_bias_field)
71
-
72
- # Convert back to numpy array and return
73
- return Sitk.GetArrayFromImage(corrected_image_full_resolution)
74
-
1
+
2
+ # pyright: reportUnknownMemberType=false
3
+ # pyright: reportUnknownArgumentType=false
4
+ # pyright: reportUnknownVariableType=false
5
+
6
+ # Imports
7
+ import SimpleITK as Sitk
8
+
9
+ from .common import Any, NDArray, check_image, np
10
+
11
+
12
+ # Functions
13
+ def bias_field_correction_image(image: NDArray[Any], ignore_dtype: bool = False) -> NDArray[Any]:
14
+ """ Apply a bias field correction to an image. (N4 Filter)
15
+
16
+ Args:
17
+ image (NDArray[Any]): Image to apply the bias field correction (can't be 8-bit unsigned integer)
18
+ ignore_dtype (bool): Ignore the dtype check
19
+ Returns:
20
+ NDArray[Any]: Image with the curvature flow filter applied
21
+
22
+ >>> ## Basic tests
23
+ >>> image = np.random.randint(0, 255, size=(10,10), dtype=np.uint8) / 255
24
+ >>> corrected = bias_field_correction_image(image)
25
+ >>> corrected.shape == image.shape
26
+ True
27
+ >>> corrected.dtype == np.float64
28
+ True
29
+
30
+ >>> ## Test invalid inputs
31
+ >>> bias_field_correction_image("not an image")
32
+ Traceback (most recent call last):
33
+ ...
34
+ AssertionError: Image must be a numpy array
35
+ """
36
+ # Check input data
37
+ check_image(image, ignore_dtype=ignore_dtype)
38
+
39
+ # If the image is 3D, convert to grayscale first
40
+ if image.ndim == 3:
41
+ image = np.mean(image, axis=-1)
42
+
43
+ # Convert numpy array to SimpleITK image
44
+ image_sitk: Sitk.Image = Sitk.GetImageFromArray(image)
45
+
46
+ # Create binary mask of the head region
47
+ transformed: Sitk.Image = Sitk.RescaleIntensity(image_sitk) # Normalize intensities
48
+ transformed = Sitk.LiThreshold(transformed, 0, 1) # Apply Li thresholding
49
+ head_mask: Sitk.Image = transformed
50
+
51
+ # Downsample images to speed up bias field estimation
52
+ shrink_factor: int = 4 # Reduce image size by factor of 4
53
+ input_image: Sitk.Image = Sitk.Shrink(
54
+ image_sitk,
55
+ [shrink_factor] * image_sitk.GetDimension() # Apply shrink factor to all dimensions
56
+ )
57
+ mask_image: Sitk.Image = Sitk.Shrink(
58
+ head_mask,
59
+ [shrink_factor] * image_sitk.GetDimension()
60
+ )
61
+
62
+ # Apply N4 bias field correction
63
+ corrector = Sitk.N4BiasFieldCorrectionImageFilter()
64
+ corrector.Execute(input_image, mask_image)
65
+
66
+ # Get estimated bias field and apply correction
67
+ log_bias_field: Sitk.Image = Sitk.Cast(
68
+ corrector.GetLogBiasFieldAsImage(image_sitk), Sitk.sitkFloat64
69
+ )
70
+ corrected_image_full_resolution: Sitk.Image = image_sitk / Sitk.Exp(log_bias_field)
71
+
72
+ # Convert back to numpy array and return
73
+ return Sitk.GetArrayFromImage(corrected_image_full_resolution)
74
+