edgefirst-validator 4.2.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 (73) hide show
  1. deepview/modelpack/utils/argmax.py +16 -0
  2. edgefirst/validator/__init__.py +1 -0
  3. edgefirst/validator/__main__.py +375 -0
  4. edgefirst/validator/datasets/__init__.py +118 -0
  5. edgefirst/validator/datasets/cache.py +296 -0
  6. edgefirst/validator/datasets/core.py +250 -0
  7. edgefirst/validator/datasets/darknet.py +446 -0
  8. edgefirst/validator/datasets/database.py +1067 -0
  9. edgefirst/validator/datasets/instance/__init__.py +4 -0
  10. edgefirst/validator/datasets/instance/core.py +222 -0
  11. edgefirst/validator/datasets/instance/detection.py +145 -0
  12. edgefirst/validator/datasets/instance/multitask.py +80 -0
  13. edgefirst/validator/datasets/instance/segmentation.py +120 -0
  14. edgefirst/validator/datasets/utils/fetch.py +682 -0
  15. edgefirst/validator/datasets/utils/readers.py +425 -0
  16. edgefirst/validator/datasets/utils/transformations.py +1695 -0
  17. edgefirst/validator/evaluators/__init__.py +17 -0
  18. edgefirst/validator/evaluators/callbacks/__init__.py +3 -0
  19. edgefirst/validator/evaluators/callbacks/core.py +192 -0
  20. edgefirst/validator/evaluators/callbacks/plots.py +900 -0
  21. edgefirst/validator/evaluators/callbacks/studio.py +234 -0
  22. edgefirst/validator/evaluators/core.py +257 -0
  23. edgefirst/validator/evaluators/detection.py +749 -0
  24. edgefirst/validator/evaluators/multitask.py +270 -0
  25. edgefirst/validator/evaluators/parameters/__init__.py +53 -0
  26. edgefirst/validator/evaluators/parameters/core.py +554 -0
  27. edgefirst/validator/evaluators/parameters/dataset.py +239 -0
  28. edgefirst/validator/evaluators/parameters/model.py +338 -0
  29. edgefirst/validator/evaluators/parameters/validation.py +528 -0
  30. edgefirst/validator/evaluators/segmentation.py +729 -0
  31. edgefirst/validator/evaluators/utils/__init__.py +3 -0
  32. edgefirst/validator/evaluators/utils/classify.py +292 -0
  33. edgefirst/validator/evaluators/utils/match.py +262 -0
  34. edgefirst/validator/evaluators/utils/timer.py +132 -0
  35. edgefirst/validator/metrics/__init__.py +9 -0
  36. edgefirst/validator/metrics/data/__init__.py +7 -0
  37. edgefirst/validator/metrics/data/label.py +668 -0
  38. edgefirst/validator/metrics/data/metrics.py +759 -0
  39. edgefirst/validator/metrics/data/plots.py +476 -0
  40. edgefirst/validator/metrics/data/stats.py +507 -0
  41. edgefirst/validator/metrics/detection.py +595 -0
  42. edgefirst/validator/metrics/segmentation.py +173 -0
  43. edgefirst/validator/metrics/utils/math.py +717 -0
  44. edgefirst/validator/publishers/__init__.py +3 -0
  45. edgefirst/validator/publishers/console.py +147 -0
  46. edgefirst/validator/publishers/studio.py +128 -0
  47. edgefirst/validator/publishers/tensorboard.py +119 -0
  48. edgefirst/validator/publishers/utils/logger.py +111 -0
  49. edgefirst/validator/publishers/utils/table.py +403 -0
  50. edgefirst/validator/runners/__init__.py +8 -0
  51. edgefirst/validator/runners/core.py +727 -0
  52. edgefirst/validator/runners/deepviewrt.py +177 -0
  53. edgefirst/validator/runners/hailo.py +263 -0
  54. edgefirst/validator/runners/keras.py +150 -0
  55. edgefirst/validator/runners/kinara.py +265 -0
  56. edgefirst/validator/runners/offline.py +228 -0
  57. edgefirst/validator/runners/onnx.py +241 -0
  58. edgefirst/validator/runners/processing/decode.py +320 -0
  59. edgefirst/validator/runners/processing/dvapi.py +4192 -0
  60. edgefirst/validator/runners/processing/nms.py +637 -0
  61. edgefirst/validator/runners/processing/outputs.py +507 -0
  62. edgefirst/validator/runners/tensorrt.py +321 -0
  63. edgefirst/validator/runners/tflite.py +221 -0
  64. edgefirst/validator/validate.py +843 -0
  65. edgefirst/validator/visualize/__init__.py +3 -0
  66. edgefirst/validator/visualize/detection.py +623 -0
  67. edgefirst/validator/visualize/segmentation.py +281 -0
  68. edgefirst/validator/visualize/utils/plots.py +635 -0
  69. edgefirst_validator-4.2.1.dist-info/METADATA +111 -0
  70. edgefirst_validator-4.2.1.dist-info/RECORD +73 -0
  71. edgefirst_validator-4.2.1.dist-info/WHEEL +5 -0
  72. edgefirst_validator-4.2.1.dist-info/entry_points.txt +2 -0
  73. edgefirst_validator-4.2.1.dist-info/top_level.txt +2 -0
@@ -0,0 +1,281 @@
1
+ import numpy as np
2
+ from PIL import Image, ImageDraw, ImageFont
3
+
4
+ from edgefirst.validator.datasets import SegmentationInstance
5
+
6
+
7
+ class Colors:
8
+ """
9
+ Ultralytics color palette for visualization and plotting.
10
+ Source: https://github.com/ultralytics/ultralytics/blob/main/ultralytics/utils/plotting.py#L19
11
+
12
+ This class provides methods to work with the Ultralytics color palette,
13
+ including converting hex color codes to RGB values and accessing predefined
14
+ color schemes for object detection and pose estimation.
15
+
16
+ Attributes
17
+ ----------
18
+ palette: List[tuple]
19
+ List of RGB color tuples for general use.
20
+ n: int
21
+ The number of colors in the palette.
22
+ pose_palette: np.ndarray
23
+ A specific color palette array for pose estimation with dtype np.uint8.
24
+
25
+ Examples
26
+ --------
27
+ >>> from ultralytics.utils.plotting import Colors
28
+ >>> colors = Colors()
29
+ >>> colors(5, True) # Returns BGR format: (221, 111, 255)
30
+ >>> colors(5, False) # Returns RGB format: (255, 111, 221)
31
+ """
32
+
33
+ def __init__(self):
34
+ """
35
+ Initialize colors as hex = matplotlib.colors.TABLEAU_COLORS.values().
36
+ """
37
+ hexs = (
38
+ "042AFF",
39
+ "0BDBEB",
40
+ "F3F3F3",
41
+ "00DFB7",
42
+ "111F68",
43
+ "FF6FDD",
44
+ "FF444F",
45
+ "CCED00",
46
+ "00F344",
47
+ "BD00FF",
48
+ "00B4FF",
49
+ "DD00BA",
50
+ "00FFFF",
51
+ "26C000",
52
+ "01FFB3",
53
+ "7D24FF",
54
+ "7B0068",
55
+ "FF1B6C",
56
+ "FC6D2F",
57
+ "A2FF0B",
58
+ )
59
+ self.palette = [self.hex2rgb(f"#{c}") for c in hexs]
60
+ self.n = len(self.palette)
61
+ self.pose_palette = np.array(
62
+ [
63
+ [255, 128, 0],
64
+ [255, 153, 51],
65
+ [255, 178, 102],
66
+ [230, 230, 0],
67
+ [255, 153, 255],
68
+ [153, 204, 255],
69
+ [255, 102, 255],
70
+ [255, 51, 255],
71
+ [102, 178, 255],
72
+ [51, 153, 255],
73
+ [255, 153, 153],
74
+ [255, 102, 102],
75
+ [255, 51, 51],
76
+ [153, 255, 153],
77
+ [102, 255, 102],
78
+ [51, 255, 51],
79
+ [0, 255, 0],
80
+ [0, 0, 255],
81
+ [255, 0, 0],
82
+ [255, 255, 255],
83
+ ],
84
+ dtype=np.uint8,
85
+ )
86
+
87
+ def __call__(self, i: int, bgr: bool = False) -> tuple:
88
+ """
89
+ Convert hex color codes to RGB values.
90
+
91
+ Parameters
92
+ ----------
93
+ i : int
94
+ Index of the color in the palette.
95
+ bgr : bool, optional
96
+ If True, return color in BGR format. Default is False.
97
+
98
+ Returns
99
+ -------
100
+ tuple
101
+ A 3-element tuple representing the RGB or BGR color.
102
+ """
103
+ c = self.palette[int(i) % self.n]
104
+ return (c[2], c[1], c[0]) if bgr else c
105
+
106
+ @staticmethod
107
+ def hex2rgb(h: str) -> tuple:
108
+ """
109
+ Convert hex color codes to RGB values (i.e. default PIL order).
110
+
111
+ Parameters
112
+ ----------
113
+ h : str
114
+ Hex color string (e.g. "#FF00AA").
115
+
116
+ Returns
117
+ -------
118
+ tuple
119
+ A 3-element tuple representing the RGB color.
120
+ """
121
+ return tuple(int(h[1 + i: 1 + i + 2], 16) for i in (0, 2, 4))
122
+
123
+
124
+ class SegmentationDrawer:
125
+ """
126
+ This class draws segmentation masks from the ground truth and
127
+ model predictions on the image.
128
+ """
129
+
130
+ def __init__(self):
131
+ self.font = ImageFont.load_default()
132
+ self.colors = Colors()
133
+
134
+ def mask2maskimage(
135
+ self,
136
+ gt_instance: SegmentationInstance,
137
+ dt_instance: SegmentationInstance,
138
+ semantic: bool = True
139
+ ) -> Image.Image:
140
+ """
141
+ Masks the original image and returns the original image
142
+ with mask prediction on the left and mask ground truth on the right.
143
+ This method is used for drawing semantic segmentation masks as
144
+ the input.
145
+
146
+ Parameters
147
+ ----------
148
+ gt_instance: SegmentationInstance
149
+ This object contains the ground truth mask.
150
+ dt_instance: SegmentationInstance
151
+ This object contains the predictions mask.
152
+ semantic: bool
153
+ The condition that specifies whether or not the
154
+ segmentation masks are semantic or instance.
155
+
156
+ Returns
157
+ -------
158
+ Image.Image
159
+ The image with drawn masks where on the right pane
160
+ shows the ground truth mask and on the left pane shows
161
+ the prediction mask.
162
+ """
163
+
164
+ gt_image = Image.fromarray(np.uint8(gt_instance.visual_image))
165
+ if dt_instance.visual_image is not None:
166
+ dt_image = Image.fromarray(np.uint8(dt_instance.visual_image))
167
+ else:
168
+ dt_image = gt_image
169
+
170
+ gt_mask = gt_instance.mask
171
+ dt_mask = dt_instance.mask
172
+
173
+ # Create image from numpy masks.
174
+ mask_gt = self.mask2image(gt_mask,
175
+ labels=gt_instance.labels,
176
+ semantic=semantic)
177
+ mask_dt = self.mask2image(dt_mask,
178
+ labels=dt_instance.labels,
179
+ semantic=semantic)
180
+
181
+ image_gt = gt_image.convert("RGBA")
182
+ image_dt = dt_image.convert("RGBA")
183
+ mask_image_gt = Image.alpha_composite(image_gt, mask_gt).convert("RGB")
184
+ mask_image_dt = Image.alpha_composite(image_dt, mask_dt).convert("RGB")
185
+
186
+ dst = Image.new(
187
+ 'RGB',
188
+ (mask_image_dt.width + mask_image_gt.width, mask_image_dt.height))
189
+ dst.paste(mask_image_gt, (0, 0))
190
+ dst.paste(mask_image_dt, (mask_image_dt.width, 0))
191
+
192
+ draw_text = ImageDraw.Draw(dst)
193
+ draw_text.text(
194
+ (0, 0),
195
+ "GROUND TRUTH",
196
+ font=self.font,
197
+ align='left',
198
+ fill=(0, 0, 0)
199
+ )
200
+ draw_text.text(
201
+ (mask_image_dt.width, 0),
202
+ "MODEL PREDICTION",
203
+ font=self.font,
204
+ align='left',
205
+ fill=(0, 0, 0)
206
+ )
207
+ return dst
208
+
209
+ def mask2image(
210
+ self,
211
+ mask: np.ndarray,
212
+ labels: list = [],
213
+ constant: int = None,
214
+ semantic: bool = True,
215
+ alpha: int = 130
216
+ ) -> Image.Image:
217
+ """
218
+ Transform a NumPy array of mask into an RGBA image.
219
+
220
+ Parameter
221
+ ---------
222
+ mask: np.ndarray
223
+ Array (height, width) representing the mask.
224
+ labels: list
225
+ For instance segmentation, provides the integer label
226
+ for each mask.
227
+ constant: int
228
+ Specify a constant to color the mask with a single color
229
+ based on the constant specified which is the index to the
230
+ list of colors. By default, None is provided and colors
231
+ the masks based on the unique values in the mask.
232
+ semantic: bool
233
+ The condition that specifies whether or not the
234
+ segmentation masks are semantic or instance.
235
+ alpha: int
236
+ The constant value for the alpha channel.
237
+
238
+ Returns
239
+ -------
240
+ Image.Image
241
+ The masked image.
242
+ """
243
+ # Transform dimension of masks from a 2D numpy array to 4D into RGBA.
244
+ if len(mask.shape) > 2:
245
+ _, height, width = mask.shape
246
+ else:
247
+ height, width = mask.shape
248
+ mask_4_channels = np.zeros((height, width, 4), dtype=np.uint8)
249
+
250
+ # Used for drawing an instance segmentation mask on the image
251
+ # based on the constance assigned for the mask label.
252
+ if constant:
253
+ # Assign all classes with color white. An instance segmentation
254
+ # mask is binary which has 0 and 1 values.
255
+ mask_4_channels[mask > 0] = 255
256
+ # Temporarily unpack the bands for readability.
257
+ red, green, blue, _ = mask_4_channels.T
258
+ # Areas of all classes.
259
+ u_areas = (red == 255) & (blue == 255) & (green == 255)
260
+ # Color all classes with the constant value.
261
+ mask_4_channels[..., :][u_areas.T] = np.append(
262
+ self.colors(constant), alpha)
263
+ else:
264
+ # For instance segmentation, the labels should be provided.
265
+ # Otherwise, the labels are taken from the unique values
266
+ # in the mask for semantic segmentation.
267
+ if semantic:
268
+ labels = np.sort(np.unique(mask))
269
+ for label in labels:
270
+ if label != 0:
271
+ # Designate a color for each class.
272
+ mask_4_channels[mask == label] = \
273
+ np.append(self.colors(label), alpha)
274
+ else:
275
+ for label, m in zip(labels, mask):
276
+ # Designate a color for each class.
277
+ mask_4_channels[m > 0] = np.append(
278
+ self.colors(label), alpha)
279
+
280
+ # Convert array to image object for image processing.
281
+ return Image.fromarray(mask_4_channels.astype(np.uint8))