stouputils 1.14.0__py3-none-any.whl → 1.14.1__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 +13 -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.1.dist-info}/METADATA +1 -1
  105. stouputils-1.14.1.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.1.dist-info}/WHEEL +0 -0
  108. {stouputils-1.14.0.dist-info → stouputils-1.14.1.dist-info}/entry_points.txt +0 -0
@@ -1,123 +1,123 @@
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
- # Constants
11
- VALID_SPACES: list[str] = ["lab", "ycbcr", "hsv"]
12
-
13
- # Color space conversion constants
14
- COLOR_SPACE_CONSTANTS: dict[str, tuple[int, int, int]] = {
15
- "lab": (cv2.COLOR_BGR2LAB, cv2.COLOR_LAB2BGR, 0), # L channel index is 0
16
- "ycbcr": (cv2.COLOR_BGR2YCrCb, cv2.COLOR_YCrCb2BGR, 0), # Y channel index is 0
17
- "hsv": (cv2.COLOR_BGR2HSV, cv2.COLOR_HSV2BGR, 2), # V channel index is 2
18
- }
19
-
20
-
21
- # Functions
22
- def histogram_equalization_image(
23
- image: NDArray[Any],
24
- color_space: Literal["lab", "ycbcr", "hsv"] = "lab",
25
- ignore_dtype: bool = False,
26
- ) -> NDArray[Any]:
27
- """ Apply standard histogram equalization to an image.
28
-
29
- Histogram equalization improves the contrast in images by stretching
30
- the intensity range to utilize the full range of intensity values.
31
-
32
- Args:
33
- image (NDArray[Any]): Image to apply histogram equalization to
34
- color_space (str): Color space to use for equalization ("lab", "ycbcr", or "hsv")
35
- "lab": CIELab color space (perceptually uniform, best visual fidelity)
36
- "ycbcr": YCbCr color space (fast, good balance)
37
- "hsv": HSV color space (intuitive, may cause color shifts)
38
- ignore_dtype (bool): Ignore the dtype check
39
- Returns:
40
- NDArray[Any]: Image with histogram equalization applied
41
-
42
- >>> ## Basic tests
43
- >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
44
- >>> histogram_equalization_image(image.astype(np.uint8)).tolist()
45
- [[0, 32, 64], [96, 128, 159], [191, 223, 255]]
46
-
47
- >>> img = np.full((5,5), 128, dtype=np.uint8)
48
- >>> img[1:3, 1:3] = 200 # Create a bright region
49
- >>> histogram_equalization_image(img).tolist()
50
- [[0, 0, 0, 0, 0], [0, 255, 255, 0, 0], [0, 255, 255, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
51
-
52
- >>> rgb = np.full((3,3,3), 128, dtype=np.uint8)
53
- >>> rgb[1, 1, :] = 50 # Create a dark region
54
- >>> equalized_rgb = histogram_equalization_image(rgb)
55
- >>> bool(np.std(equalized_rgb) > np.std(rgb)) # Should enhance contrast
56
- True
57
- >>> equalized_rgb.tolist()
58
- [[[255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [0, 0, 0], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255]]]
59
-
60
- >>> ## Test each color space
61
- >>> test_img = np.zeros((20, 20, 3), dtype=np.uint8)
62
- >>> test_img[5:15, 5:15] = 200 # Add contrast region
63
-
64
- >>> # Test LAB color space
65
- >>> lab_result = histogram_equalization_image(test_img, color_space="lab")
66
- >>> isinstance(lab_result, np.ndarray) and lab_result.shape == test_img.shape
67
- True
68
- >>> bool(np.std(lab_result) > np.std(test_img)) # Verify contrast enhancement
69
- True
70
-
71
- >>> # Test YCbCr color space
72
- >>> ycbcr_result = histogram_equalization_image(test_img, color_space="ycbcr")
73
- >>> isinstance(ycbcr_result, np.ndarray) and ycbcr_result.shape == test_img.shape
74
- True
75
- >>> bool(np.std(ycbcr_result) > np.std(test_img)) # Verify contrast enhancement
76
- True
77
-
78
- >>> # Test HSV color space
79
- >>> hsv_result = histogram_equalization_image(test_img, color_space="hsv")
80
- >>> isinstance(hsv_result, np.ndarray) and hsv_result.shape == test_img.shape
81
- True
82
- >>> bool(np.std(hsv_result) > np.std(test_img)) # Verify contrast enhancement
83
- True
84
-
85
- >>> ## Test invalid inputs
86
- >>> histogram_equalization_image("not an image")
87
- Traceback (most recent call last):
88
- ...
89
- AssertionError: Image must be a numpy array
90
-
91
- >>> histogram_equalization_image(rgb, "invalid_space")
92
- Traceback (most recent call last):
93
- ...
94
- AssertionError: color_space must be one of: lab, ycbcr, hsv
95
- """ # noqa: E501
96
- # Check input data
97
- check_image(image, ignore_dtype=ignore_dtype)
98
- lowered_color_space = color_space.lower()
99
- assert lowered_color_space in VALID_SPACES, f"color_space must be one of: {', '.join(VALID_SPACES)}"
100
-
101
- # Handle different image types
102
- if len(image.shape) == 2:
103
- # Grayscale image - just apply histogram equalization directly
104
- return cv2.equalizeHist(image)
105
- else:
106
- # Color image - apply equalization based on selected color space
107
- convert_to, convert_from, channel_idx = COLOR_SPACE_CONSTANTS[lowered_color_space]
108
-
109
- # Convert to target color space
110
- converted: NDArray[Any] = cv2.cvtColor(image, convert_to)
111
-
112
- # Split channels
113
- channels: list[NDArray[Any]] = list(cv2.split(converted))
114
-
115
- # Apply histogram equalization to the appropriate channel
116
- channels[channel_idx] = cv2.equalizeHist(channels[channel_idx])
117
-
118
- # Merge channels
119
- result: NDArray[Any] = cv2.merge(channels)
120
-
121
- # Convert back to BGR
122
- return cv2.cvtColor(result, convert_from)
123
-
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
+ # Constants
11
+ VALID_SPACES: list[str] = ["lab", "ycbcr", "hsv"]
12
+
13
+ # Color space conversion constants
14
+ COLOR_SPACE_CONSTANTS: dict[str, tuple[int, int, int]] = {
15
+ "lab": (cv2.COLOR_BGR2LAB, cv2.COLOR_LAB2BGR, 0), # L channel index is 0
16
+ "ycbcr": (cv2.COLOR_BGR2YCrCb, cv2.COLOR_YCrCb2BGR, 0), # Y channel index is 0
17
+ "hsv": (cv2.COLOR_BGR2HSV, cv2.COLOR_HSV2BGR, 2), # V channel index is 2
18
+ }
19
+
20
+
21
+ # Functions
22
+ def histogram_equalization_image(
23
+ image: NDArray[Any],
24
+ color_space: Literal["lab", "ycbcr", "hsv"] = "lab",
25
+ ignore_dtype: bool = False,
26
+ ) -> NDArray[Any]:
27
+ """ Apply standard histogram equalization to an image.
28
+
29
+ Histogram equalization improves the contrast in images by stretching
30
+ the intensity range to utilize the full range of intensity values.
31
+
32
+ Args:
33
+ image (NDArray[Any]): Image to apply histogram equalization to
34
+ color_space (str): Color space to use for equalization ("lab", "ycbcr", or "hsv")
35
+ "lab": CIELab color space (perceptually uniform, best visual fidelity)
36
+ "ycbcr": YCbCr color space (fast, good balance)
37
+ "hsv": HSV color space (intuitive, may cause color shifts)
38
+ ignore_dtype (bool): Ignore the dtype check
39
+ Returns:
40
+ NDArray[Any]: Image with histogram equalization applied
41
+
42
+ >>> ## Basic tests
43
+ >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
44
+ >>> histogram_equalization_image(image.astype(np.uint8)).tolist()
45
+ [[0, 32, 64], [96, 128, 159], [191, 223, 255]]
46
+
47
+ >>> img = np.full((5,5), 128, dtype=np.uint8)
48
+ >>> img[1:3, 1:3] = 200 # Create a bright region
49
+ >>> histogram_equalization_image(img).tolist()
50
+ [[0, 0, 0, 0, 0], [0, 255, 255, 0, 0], [0, 255, 255, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
51
+
52
+ >>> rgb = np.full((3,3,3), 128, dtype=np.uint8)
53
+ >>> rgb[1, 1, :] = 50 # Create a dark region
54
+ >>> equalized_rgb = histogram_equalization_image(rgb)
55
+ >>> bool(np.std(equalized_rgb) > np.std(rgb)) # Should enhance contrast
56
+ True
57
+ >>> equalized_rgb.tolist()
58
+ [[[255, 255, 255], [255, 255, 255], [255, 255, 255]], [[255, 255, 255], [0, 0, 0], [255, 255, 255]], [[255, 255, 255], [255, 255, 255], [255, 255, 255]]]
59
+
60
+ >>> ## Test each color space
61
+ >>> test_img = np.zeros((20, 20, 3), dtype=np.uint8)
62
+ >>> test_img[5:15, 5:15] = 200 # Add contrast region
63
+
64
+ >>> # Test LAB color space
65
+ >>> lab_result = histogram_equalization_image(test_img, color_space="lab")
66
+ >>> isinstance(lab_result, np.ndarray) and lab_result.shape == test_img.shape
67
+ True
68
+ >>> bool(np.std(lab_result) > np.std(test_img)) # Verify contrast enhancement
69
+ True
70
+
71
+ >>> # Test YCbCr color space
72
+ >>> ycbcr_result = histogram_equalization_image(test_img, color_space="ycbcr")
73
+ >>> isinstance(ycbcr_result, np.ndarray) and ycbcr_result.shape == test_img.shape
74
+ True
75
+ >>> bool(np.std(ycbcr_result) > np.std(test_img)) # Verify contrast enhancement
76
+ True
77
+
78
+ >>> # Test HSV color space
79
+ >>> hsv_result = histogram_equalization_image(test_img, color_space="hsv")
80
+ >>> isinstance(hsv_result, np.ndarray) and hsv_result.shape == test_img.shape
81
+ True
82
+ >>> bool(np.std(hsv_result) > np.std(test_img)) # Verify contrast enhancement
83
+ True
84
+
85
+ >>> ## Test invalid inputs
86
+ >>> histogram_equalization_image("not an image")
87
+ Traceback (most recent call last):
88
+ ...
89
+ AssertionError: Image must be a numpy array
90
+
91
+ >>> histogram_equalization_image(rgb, "invalid_space")
92
+ Traceback (most recent call last):
93
+ ...
94
+ AssertionError: color_space must be one of: lab, ycbcr, hsv
95
+ """ # noqa: E501
96
+ # Check input data
97
+ check_image(image, ignore_dtype=ignore_dtype)
98
+ lowered_color_space = color_space.lower()
99
+ assert lowered_color_space in VALID_SPACES, f"color_space must be one of: {', '.join(VALID_SPACES)}"
100
+
101
+ # Handle different image types
102
+ if len(image.shape) == 2:
103
+ # Grayscale image - just apply histogram equalization directly
104
+ return cv2.equalizeHist(image)
105
+ else:
106
+ # Color image - apply equalization based on selected color space
107
+ convert_to, convert_from, channel_idx = COLOR_SPACE_CONSTANTS[lowered_color_space]
108
+
109
+ # Convert to target color space
110
+ converted: NDArray[Any] = cv2.cvtColor(image, convert_to)
111
+
112
+ # Split channels
113
+ channels: list[NDArray[Any]] = list(cv2.split(converted))
114
+
115
+ # Apply histogram equalization to the appropriate channel
116
+ channels[channel_idx] = cv2.equalizeHist(channels[channel_idx])
117
+
118
+ # Merge channels
119
+ result: NDArray[Any] = cv2.merge(channels)
120
+
121
+ # Convert back to BGR
122
+ return cv2.cvtColor(result, convert_from)
123
+
@@ -1,64 +1,64 @@
1
-
2
- # Imports
3
- from .common import Any, NDArray, check_image, np
4
-
5
-
6
- # Function
7
- def invert_image(image: NDArray[Any], ignore_dtype: bool = False) -> NDArray[Any]:
8
- """ Invert the colors of an image.
9
-
10
- This function inverts the colors of the input image by subtracting each pixel value
11
- from the maximum possible value based on the image type.
12
-
13
- Args:
14
- image (NDArray[Any]): Input image as a NumPy array.
15
- ignore_dtype (bool): Ignore the dtype check.
16
- Returns:
17
- NDArray[Any]: Image with inverted colors.
18
-
19
- >>> ## Basic tests
20
- >>> image = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]], dtype=np.uint8)
21
- >>> inverted = invert_image(image)
22
- >>> inverted.tolist()
23
- [[245, 235, 225], [215, 205, 195], [185, 175, 165]]
24
-
25
- >>> # Test with floating point image
26
- >>> float_img = np.array([[0.1, 0.2], [0.3, 0.4]], dtype=np.float32)
27
- >>> [round(float(x), 1) for x in invert_image(float_img).flatten()]
28
- [0.9, 0.8, 0.7, 0.6]
29
-
30
- >>> # Test with RGB image
31
- >>> rgb = np.zeros((2, 2, 3), dtype=np.uint8)
32
- >>> rgb[0, 0] = [255, 0, 0] # Red pixel
33
- >>> inverted_rgb = invert_image(rgb)
34
- >>> inverted_rgb[0, 0].tolist()
35
- [0, 255, 255]
36
-
37
- >>> ## Test invalid inputs
38
- >>> invert_image("not an image")
39
- Traceback (most recent call last):
40
- ...
41
- AssertionError: Image must be a numpy array
42
- """
43
- # Check input data
44
- check_image(image, ignore_dtype=ignore_dtype)
45
-
46
- # Get the maximum value based on the image's data type
47
- if image.dtype == np.uint8:
48
- max_value = 255
49
- elif image.dtype == np.uint16:
50
- max_value = 65535
51
- elif image.dtype == np.float32 or image.dtype == np.float64:
52
- # For float images, we assume range [0, 1]
53
- max_value = 1.0
54
- else:
55
- # Default case, assuming 8-bit
56
- max_value = 255
57
- image = image.astype(np.uint8)
58
-
59
- # Invert the image
60
- inverted = max_value - image
61
-
62
- # Ensure we return the same dtype as the input
63
- return inverted.astype(image.dtype)
64
-
1
+
2
+ # Imports
3
+ from .common import Any, NDArray, check_image, np
4
+
5
+
6
+ # Function
7
+ def invert_image(image: NDArray[Any], ignore_dtype: bool = False) -> NDArray[Any]:
8
+ """ Invert the colors of an image.
9
+
10
+ This function inverts the colors of the input image by subtracting each pixel value
11
+ from the maximum possible value based on the image type.
12
+
13
+ Args:
14
+ image (NDArray[Any]): Input image as a NumPy array.
15
+ ignore_dtype (bool): Ignore the dtype check.
16
+ Returns:
17
+ NDArray[Any]: Image with inverted colors.
18
+
19
+ >>> ## Basic tests
20
+ >>> image = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]], dtype=np.uint8)
21
+ >>> inverted = invert_image(image)
22
+ >>> inverted.tolist()
23
+ [[245, 235, 225], [215, 205, 195], [185, 175, 165]]
24
+
25
+ >>> # Test with floating point image
26
+ >>> float_img = np.array([[0.1, 0.2], [0.3, 0.4]], dtype=np.float32)
27
+ >>> [round(float(x), 1) for x in invert_image(float_img).flatten()]
28
+ [0.9, 0.8, 0.7, 0.6]
29
+
30
+ >>> # Test with RGB image
31
+ >>> rgb = np.zeros((2, 2, 3), dtype=np.uint8)
32
+ >>> rgb[0, 0] = [255, 0, 0] # Red pixel
33
+ >>> inverted_rgb = invert_image(rgb)
34
+ >>> inverted_rgb[0, 0].tolist()
35
+ [0, 255, 255]
36
+
37
+ >>> ## Test invalid inputs
38
+ >>> invert_image("not an image")
39
+ Traceback (most recent call last):
40
+ ...
41
+ AssertionError: Image must be a numpy array
42
+ """
43
+ # Check input data
44
+ check_image(image, ignore_dtype=ignore_dtype)
45
+
46
+ # Get the maximum value based on the image's data type
47
+ if image.dtype == np.uint8:
48
+ max_value = 255
49
+ elif image.dtype == np.uint16:
50
+ max_value = 65535
51
+ elif image.dtype == np.float32 or image.dtype == np.float64:
52
+ # For float images, we assume range [0, 1]
53
+ max_value = 1.0
54
+ else:
55
+ # Default case, assuming 8-bit
56
+ max_value = 255
57
+ image = image.astype(np.uint8)
58
+
59
+ # Invert the image
60
+ inverted = max_value - image
61
+
62
+ # Ensure we return the same dtype as the input
63
+ return inverted.astype(image.dtype)
64
+
@@ -1,60 +1,60 @@
1
-
2
- # pyright: reportUnknownMemberType=false
3
- # pyright: reportUnknownVariableType=false
4
- # pyright: reportUnknownArgumentType=false
5
- # pyright: reportAttributeAccessIssue=false
6
- # pyright: reportArgumentType=false
7
- # pyright: reportCallIssue=false
8
-
9
- # Imports
10
- from .common import Any, NDArray, check_image, cv2, np
11
-
12
-
13
- # Functions
14
- def laplacian_image(image: NDArray[Any], kernel_size: int = 3, ignore_dtype: bool = False) -> NDArray[Any]:
15
- """ Apply Laplacian edge detection to an image.
16
-
17
- Args:
18
- image (NDArray[Any]): Image to apply Laplacian edge detection
19
- kernel_size (int): Size of the kernel (must be odd)
20
- ignore_dtype (bool): Ignore the dtype check
21
- Returns:
22
- NDArray[Any]: Image with Laplacian edge detection applied
23
-
24
- >>> ## Basic tests
25
- >>> image = np.array([[100, 150, 200], [50, 125, 175], [25, 75, 225]])
26
- >>> edges = laplacian_image(image.astype(np.uint8))
27
- >>> edges.shape == image.shape[:2] # Laplacian returns single channel
28
- True
29
-
30
- >>> rgb = np.random.randint(0, 256, (3,3,3), dtype=np.uint8)
31
- >>> edges_rgb = laplacian_image(rgb)
32
- >>> edges_rgb.shape == rgb.shape[:2] # Laplacian returns single channel
33
- True
34
-
35
- >>> ## Test invalid inputs
36
- >>> laplacian_image("not an image")
37
- Traceback (most recent call last):
38
- ...
39
- AssertionError: Image must be a numpy array
40
-
41
- >>> laplacian_image(image.astype(np.uint8), kernel_size=2)
42
- Traceback (most recent call last):
43
- ...
44
- AssertionError: kernel_size must be odd, got 2
45
- """
46
- # Check input data
47
- check_image(image, ignore_dtype=ignore_dtype)
48
- assert kernel_size % 2 == 1, f"kernel_size must be odd, got {kernel_size}"
49
-
50
- # Convert to grayscale if needed
51
- if len(image.shape) > 2:
52
- image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
53
-
54
- # Apply Laplacian edge detection
55
- laplacian: NDArray[Any] = cv2.Laplacian(image, cv2.CV_64F, ksize=kernel_size)
56
-
57
- # Convert back to uint8 and normalize to 0-255 range
58
- normalized: NDArray[Any] = cv2.normalize(laplacian, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
59
- return normalized.astype(np.uint8)
60
-
1
+
2
+ # pyright: reportUnknownMemberType=false
3
+ # pyright: reportUnknownVariableType=false
4
+ # pyright: reportUnknownArgumentType=false
5
+ # pyright: reportAttributeAccessIssue=false
6
+ # pyright: reportArgumentType=false
7
+ # pyright: reportCallIssue=false
8
+
9
+ # Imports
10
+ from .common import Any, NDArray, check_image, cv2, np
11
+
12
+
13
+ # Functions
14
+ def laplacian_image(image: NDArray[Any], kernel_size: int = 3, ignore_dtype: bool = False) -> NDArray[Any]:
15
+ """ Apply Laplacian edge detection to an image.
16
+
17
+ Args:
18
+ image (NDArray[Any]): Image to apply Laplacian edge detection
19
+ kernel_size (int): Size of the kernel (must be odd)
20
+ ignore_dtype (bool): Ignore the dtype check
21
+ Returns:
22
+ NDArray[Any]: Image with Laplacian edge detection applied
23
+
24
+ >>> ## Basic tests
25
+ >>> image = np.array([[100, 150, 200], [50, 125, 175], [25, 75, 225]])
26
+ >>> edges = laplacian_image(image.astype(np.uint8))
27
+ >>> edges.shape == image.shape[:2] # Laplacian returns single channel
28
+ True
29
+
30
+ >>> rgb = np.random.randint(0, 256, (3,3,3), dtype=np.uint8)
31
+ >>> edges_rgb = laplacian_image(rgb)
32
+ >>> edges_rgb.shape == rgb.shape[:2] # Laplacian returns single channel
33
+ True
34
+
35
+ >>> ## Test invalid inputs
36
+ >>> laplacian_image("not an image")
37
+ Traceback (most recent call last):
38
+ ...
39
+ AssertionError: Image must be a numpy array
40
+
41
+ >>> laplacian_image(image.astype(np.uint8), kernel_size=2)
42
+ Traceback (most recent call last):
43
+ ...
44
+ AssertionError: kernel_size must be odd, got 2
45
+ """
46
+ # Check input data
47
+ check_image(image, ignore_dtype=ignore_dtype)
48
+ assert kernel_size % 2 == 1, f"kernel_size must be odd, got {kernel_size}"
49
+
50
+ # Convert to grayscale if needed
51
+ if len(image.shape) > 2:
52
+ image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
53
+
54
+ # Apply Laplacian edge detection
55
+ laplacian: NDArray[Any] = cv2.Laplacian(image, cv2.CV_64F, ksize=kernel_size)
56
+
57
+ # Convert back to uint8 and normalize to 0-255 range
58
+ normalized: NDArray[Any] = cv2.normalize(laplacian, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX)
59
+ return normalized.astype(np.uint8)
60
+
@@ -1,52 +1,52 @@
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 median_blur_image(image: NDArray[Any], kernel_size: int = 7, iterations: int = 1) -> NDArray[Any]:
11
- """ Apply median blur to an image.
12
-
13
- Args:
14
- image (NDArray[Any]): Image to apply median blur
15
- kernel_size (int): Kernel size for the median blur
16
- iterations (int): Number of iterations for the median blur
17
- Returns:
18
- NDArray[Any]: Image with median blur applied
19
-
20
- >>> ## Basic tests
21
- >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8)
22
- >>> adjusted = median_blur_image(image, kernel_size=7, iterations=1)
23
- >>> adjusted.tolist()
24
- [[3, 3, 3], [4, 5, 6], [7, 7, 7]]
25
- >>> adjusted.shape == image.shape
26
- True
27
- >>> adjusted.dtype == image.dtype
28
- True
29
-
30
- >>> median_blur_image(image, kernel_size=3, iterations=1).tolist()
31
- [[2, 3, 3], [4, 5, 6], [7, 7, 8]]
32
- >>> median_blur_image(image, kernel_size=3, iterations=2).tolist()
33
- [[3, 3, 3], [4, 5, 6], [7, 7, 7]]
34
- >>> median_blur_image(image, kernel_size=3, iterations=5).tolist()
35
- [[3, 3, 3], [4, 5, 6], [7, 7, 7]]
36
-
37
- >>> ## Test invalid inputs
38
- >>> median_blur_image("not an image")
39
- Traceback (most recent call last):
40
- ...
41
- AssertionError: Image must be a numpy array
42
- """
43
- # Check input data
44
- check_image(image, ignore_dtype=True)
45
-
46
- # Apply median blur
47
- for _ in range(iterations):
48
- image = cv2.medianBlur(image, kernel_size)
49
-
50
- # Return the image
51
- return image
52
-
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 median_blur_image(image: NDArray[Any], kernel_size: int = 7, iterations: int = 1) -> NDArray[Any]:
11
+ """ Apply median blur to an image.
12
+
13
+ Args:
14
+ image (NDArray[Any]): Image to apply median blur
15
+ kernel_size (int): Kernel size for the median blur
16
+ iterations (int): Number of iterations for the median blur
17
+ Returns:
18
+ NDArray[Any]: Image with median blur applied
19
+
20
+ >>> ## Basic tests
21
+ >>> image = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8)
22
+ >>> adjusted = median_blur_image(image, kernel_size=7, iterations=1)
23
+ >>> adjusted.tolist()
24
+ [[3, 3, 3], [4, 5, 6], [7, 7, 7]]
25
+ >>> adjusted.shape == image.shape
26
+ True
27
+ >>> adjusted.dtype == image.dtype
28
+ True
29
+
30
+ >>> median_blur_image(image, kernel_size=3, iterations=1).tolist()
31
+ [[2, 3, 3], [4, 5, 6], [7, 7, 8]]
32
+ >>> median_blur_image(image, kernel_size=3, iterations=2).tolist()
33
+ [[3, 3, 3], [4, 5, 6], [7, 7, 7]]
34
+ >>> median_blur_image(image, kernel_size=3, iterations=5).tolist()
35
+ [[3, 3, 3], [4, 5, 6], [7, 7, 7]]
36
+
37
+ >>> ## Test invalid inputs
38
+ >>> median_blur_image("not an image")
39
+ Traceback (most recent call last):
40
+ ...
41
+ AssertionError: Image must be a numpy array
42
+ """
43
+ # Check input data
44
+ check_image(image, ignore_dtype=True)
45
+
46
+ # Apply median blur
47
+ for _ in range(iterations):
48
+ image = cv2.medianBlur(image, kernel_size)
49
+
50
+ # Return the image
51
+ return image
52
+