supervisely 6.73.238__py3-none-any.whl → 6.73.240__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 (138) hide show
  1. supervisely/annotation/annotation.py +2 -2
  2. supervisely/api/entity_annotation/tag_api.py +11 -4
  3. supervisely/api/file_api.py +17 -3
  4. supervisely/nn/__init__.py +1 -0
  5. supervisely/nn/benchmark/__init__.py +14 -2
  6. supervisely/nn/benchmark/base_benchmark.py +84 -37
  7. supervisely/nn/benchmark/base_evaluator.py +120 -0
  8. supervisely/nn/benchmark/base_visualizer.py +265 -0
  9. supervisely/nn/benchmark/comparison/detection_visualization/text_templates.py +5 -5
  10. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/calibration_score.py +2 -2
  11. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/explore_predicttions.py +39 -16
  12. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/localization_accuracy.py +1 -1
  13. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/outcome_counts.py +4 -4
  14. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/overview.py +12 -11
  15. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/pr_curve.py +1 -1
  16. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/precision_recal_f1.py +6 -6
  17. supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/speedtest.py +3 -3
  18. supervisely/nn/benchmark/{instance_segmentation_benchmark.py → instance_segmentation/benchmark.py} +9 -3
  19. supervisely/nn/benchmark/instance_segmentation/evaluator.py +58 -0
  20. supervisely/nn/benchmark/{visualization/text_templates/instance_segmentation_text.py → instance_segmentation/text_templates.py} +53 -69
  21. supervisely/nn/benchmark/instance_segmentation/visualizer.py +18 -0
  22. supervisely/nn/benchmark/object_detection/__init__.py +0 -0
  23. supervisely/nn/benchmark/object_detection/base_vis_metric.py +51 -0
  24. supervisely/nn/benchmark/{object_detection_benchmark.py → object_detection/benchmark.py} +4 -2
  25. supervisely/nn/benchmark/object_detection/evaluation_params.yaml +2 -0
  26. supervisely/nn/benchmark/{evaluation/object_detection_evaluator.py → object_detection/evaluator.py} +67 -9
  27. supervisely/nn/benchmark/{evaluation/coco → object_detection}/metric_provider.py +13 -14
  28. supervisely/nn/benchmark/{visualization/text_templates/object_detection_text.py → object_detection/text_templates.py} +49 -41
  29. supervisely/nn/benchmark/object_detection/vis_metrics/__init__.py +48 -0
  30. supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/confidence_distribution.py +20 -24
  31. supervisely/nn/benchmark/object_detection/vis_metrics/confidence_score.py +119 -0
  32. supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/confusion_matrix.py +34 -22
  33. supervisely/nn/benchmark/object_detection/vis_metrics/explore_predictions.py +129 -0
  34. supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/f1_score_at_different_iou.py +21 -26
  35. supervisely/nn/benchmark/object_detection/vis_metrics/frequently_confused.py +137 -0
  36. supervisely/nn/benchmark/object_detection/vis_metrics/iou_distribution.py +106 -0
  37. supervisely/nn/benchmark/object_detection/vis_metrics/key_metrics.py +136 -0
  38. supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/model_predictions.py +53 -49
  39. supervisely/nn/benchmark/object_detection/vis_metrics/outcome_counts.py +188 -0
  40. supervisely/nn/benchmark/object_detection/vis_metrics/outcome_counts_per_class.py +191 -0
  41. supervisely/nn/benchmark/object_detection/vis_metrics/overview.py +116 -0
  42. supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve.py +106 -0
  43. supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve_by_class.py +49 -0
  44. supervisely/nn/benchmark/object_detection/vis_metrics/precision.py +72 -0
  45. supervisely/nn/benchmark/object_detection/vis_metrics/precision_avg_per_class.py +59 -0
  46. supervisely/nn/benchmark/object_detection/vis_metrics/recall.py +71 -0
  47. supervisely/nn/benchmark/object_detection/vis_metrics/recall_vs_precision.py +56 -0
  48. supervisely/nn/benchmark/object_detection/vis_metrics/reliability_diagram.py +110 -0
  49. supervisely/nn/benchmark/object_detection/vis_metrics/speedtest.py +151 -0
  50. supervisely/nn/benchmark/object_detection/visualizer.py +697 -0
  51. supervisely/nn/benchmark/semantic_segmentation/__init__.py +9 -0
  52. supervisely/nn/benchmark/semantic_segmentation/base_vis_metric.py +55 -0
  53. supervisely/nn/benchmark/semantic_segmentation/benchmark.py +32 -0
  54. supervisely/nn/benchmark/semantic_segmentation/evaluation_params.yaml +0 -0
  55. supervisely/nn/benchmark/semantic_segmentation/evaluator.py +162 -0
  56. supervisely/nn/benchmark/semantic_segmentation/metric_provider.py +153 -0
  57. supervisely/nn/benchmark/semantic_segmentation/text_templates.py +130 -0
  58. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/__init__.py +0 -0
  59. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/acknowledgement.py +15 -0
  60. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/classwise_error_analysis.py +57 -0
  61. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/confusion_matrix.py +92 -0
  62. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/explore_predictions.py +84 -0
  63. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/frequently_confused.py +101 -0
  64. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/iou_eou.py +45 -0
  65. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/key_metrics.py +60 -0
  66. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/model_predictions.py +107 -0
  67. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/overview.py +112 -0
  68. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/renormalized_error_ou.py +48 -0
  69. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/speedtest.py +178 -0
  70. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/vis_texts.py +21 -0
  71. supervisely/nn/benchmark/semantic_segmentation/visualizer.py +304 -0
  72. supervisely/nn/benchmark/utils/__init__.py +12 -0
  73. supervisely/nn/benchmark/utils/detection/__init__.py +2 -0
  74. supervisely/nn/benchmark/{evaluation/coco → utils/detection}/calculate_metrics.py +6 -4
  75. supervisely/nn/benchmark/utils/detection/metric_provider.py +533 -0
  76. supervisely/nn/benchmark/{coco_utils → utils/detection}/sly2coco.py +4 -4
  77. supervisely/nn/benchmark/{coco_utils/utils.py → utils/detection/utlis.py} +11 -0
  78. supervisely/nn/benchmark/utils/semantic_segmentation/__init__.py +0 -0
  79. supervisely/nn/benchmark/utils/semantic_segmentation/calculate_metrics.py +35 -0
  80. supervisely/nn/benchmark/utils/semantic_segmentation/evaluator.py +804 -0
  81. supervisely/nn/benchmark/utils/semantic_segmentation/loader.py +65 -0
  82. supervisely/nn/benchmark/utils/semantic_segmentation/utils.py +109 -0
  83. supervisely/nn/benchmark/visualization/evaluation_result.py +17 -3
  84. supervisely/nn/benchmark/visualization/vis_click_data.py +1 -1
  85. supervisely/nn/benchmark/visualization/widgets/__init__.py +3 -0
  86. supervisely/nn/benchmark/visualization/widgets/chart/chart.py +12 -4
  87. supervisely/nn/benchmark/visualization/widgets/gallery/gallery.py +35 -8
  88. supervisely/nn/benchmark/visualization/widgets/gallery/template.html +8 -4
  89. supervisely/nn/benchmark/visualization/widgets/markdown/markdown.py +1 -1
  90. supervisely/nn/benchmark/visualization/widgets/notification/notification.py +11 -7
  91. supervisely/nn/benchmark/visualization/widgets/radio_group/__init__.py +0 -0
  92. supervisely/nn/benchmark/visualization/widgets/radio_group/radio_group.py +34 -0
  93. supervisely/nn/benchmark/visualization/widgets/table/table.py +9 -3
  94. supervisely/nn/benchmark/visualization/widgets/widget.py +4 -0
  95. supervisely/project/project.py +18 -6
  96. {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/METADATA +3 -1
  97. {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/RECORD +104 -82
  98. supervisely/nn/benchmark/coco_utils/__init__.py +0 -2
  99. supervisely/nn/benchmark/evaluation/__init__.py +0 -3
  100. supervisely/nn/benchmark/evaluation/base_evaluator.py +0 -64
  101. supervisely/nn/benchmark/evaluation/coco/__init__.py +0 -2
  102. supervisely/nn/benchmark/evaluation/instance_segmentation_evaluator.py +0 -88
  103. supervisely/nn/benchmark/utils.py +0 -13
  104. supervisely/nn/benchmark/visualization/inference_speed/__init__.py +0 -19
  105. supervisely/nn/benchmark/visualization/inference_speed/speedtest_batch.py +0 -161
  106. supervisely/nn/benchmark/visualization/inference_speed/speedtest_intro.py +0 -28
  107. supervisely/nn/benchmark/visualization/inference_speed/speedtest_overview.py +0 -141
  108. supervisely/nn/benchmark/visualization/inference_speed/speedtest_real_time.py +0 -63
  109. supervisely/nn/benchmark/visualization/text_templates/inference_speed_text.py +0 -23
  110. supervisely/nn/benchmark/visualization/vis_metric_base.py +0 -337
  111. supervisely/nn/benchmark/visualization/vis_metrics/__init__.py +0 -67
  112. supervisely/nn/benchmark/visualization/vis_metrics/classwise_error_analysis.py +0 -55
  113. supervisely/nn/benchmark/visualization/vis_metrics/confidence_score.py +0 -93
  114. supervisely/nn/benchmark/visualization/vis_metrics/explorer_grid.py +0 -144
  115. supervisely/nn/benchmark/visualization/vis_metrics/frequently_confused.py +0 -115
  116. supervisely/nn/benchmark/visualization/vis_metrics/iou_distribution.py +0 -86
  117. supervisely/nn/benchmark/visualization/vis_metrics/outcome_counts.py +0 -119
  118. supervisely/nn/benchmark/visualization/vis_metrics/outcome_counts_per_class.py +0 -148
  119. supervisely/nn/benchmark/visualization/vis_metrics/overall_error_analysis.py +0 -109
  120. supervisely/nn/benchmark/visualization/vis_metrics/overview.py +0 -189
  121. supervisely/nn/benchmark/visualization/vis_metrics/percision_avg_per_class.py +0 -57
  122. supervisely/nn/benchmark/visualization/vis_metrics/pr_curve.py +0 -101
  123. supervisely/nn/benchmark/visualization/vis_metrics/pr_curve_by_class.py +0 -46
  124. supervisely/nn/benchmark/visualization/vis_metrics/precision.py +0 -56
  125. supervisely/nn/benchmark/visualization/vis_metrics/recall.py +0 -54
  126. supervisely/nn/benchmark/visualization/vis_metrics/recall_vs_precision.py +0 -57
  127. supervisely/nn/benchmark/visualization/vis_metrics/reliability_diagram.py +0 -88
  128. supervisely/nn/benchmark/visualization/vis_metrics/what_is.py +0 -23
  129. supervisely/nn/benchmark/visualization/vis_templates.py +0 -241
  130. supervisely/nn/benchmark/visualization/vis_widgets.py +0 -128
  131. supervisely/nn/benchmark/visualization/visualizer.py +0 -729
  132. /supervisely/nn/benchmark/{visualization/text_templates → instance_segmentation}/__init__.py +0 -0
  133. /supervisely/nn/benchmark/{evaluation/coco → instance_segmentation}/evaluation_params.yaml +0 -0
  134. /supervisely/nn/benchmark/{evaluation/coco → utils/detection}/metrics.py +0 -0
  135. {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/LICENSE +0 -0
  136. {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/WHEEL +0 -0
  137. {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/entry_points.txt +0 -0
  138. {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,65 @@
1
+ import os
2
+
3
+ import cv2
4
+
5
+
6
+ def build_segmentation_loader(
7
+ pred_dir,
8
+ gt_dir,
9
+ num_workers=0,
10
+ pred_label_map=None,
11
+ gt_label_map=None,
12
+ ):
13
+ import torch # pylint: disable=import-error
14
+
15
+ class SegmentationLoader(torch.utils.data.Dataset):
16
+ def __init__(
17
+ self,
18
+ pred_dir,
19
+ gt_dir,
20
+ pred_label_map=None,
21
+ gt_label_map=None,
22
+ ):
23
+ self.pred_dir = pred_dir
24
+ self.pred_files = sorted(os.listdir(self.pred_dir))
25
+ self.gt_dir = gt_dir
26
+ self.gt_files = sorted(os.listdir(self.gt_dir))
27
+ if len(self.pred_files) != len(self.gt_files):
28
+ raise RuntimeError(
29
+ f"Number of predictions({len(self.pred_files)}) and ground-truth annotations ({len(self.gt_files)}) do not match!"
30
+ )
31
+ self.pred_label_map = pred_label_map
32
+ self.gt_label_map = gt_label_map
33
+
34
+ def __len__(self):
35
+ return len(self.pred_files)
36
+
37
+ def __getitem__(self, index):
38
+ pred_path = os.path.join(self.pred_dir, self.pred_files[index])
39
+ gt_path = os.path.join(self.gt_dir, self.gt_files[index])
40
+
41
+ if self.pred_label_map:
42
+ pred = self.pred_label_map(pred)
43
+ else:
44
+ pred = cv2.imread(pred_path, cv2.IMREAD_UNCHANGED)
45
+
46
+ if self.gt_label_map:
47
+ gt = self.gt_label_map(gt)
48
+ else:
49
+ gt = cv2.imread(gt_path, cv2.IMREAD_UNCHANGED)
50
+
51
+ img_name = self.gt_files[index]
52
+ return (pred, gt, img_name)
53
+
54
+ loader = SegmentationLoader(
55
+ pred_dir=pred_dir,
56
+ gt_dir=gt_dir,
57
+ pred_label_map=pred_label_map,
58
+ gt_label_map=gt_label_map,
59
+ )
60
+ return torch.utils.data.DataLoader(
61
+ loader,
62
+ batch_size=1,
63
+ num_workers=num_workers,
64
+ collate_fn=lambda l: (l[0][0], l[0][1], l[0][2]),
65
+ )
@@ -0,0 +1,109 @@
1
+ import cv2
2
+ import numpy as np
3
+ import scipy
4
+
5
+
6
+ def one_hot(segmentation, num_classes):
7
+ # TODO: this assumes that the classes start with 0
8
+ segmentation_copy = segmentation.copy()
9
+ eye = np.eye(num_classes + 1, dtype=np.bool_)
10
+ one_hot_seg = eye[segmentation_copy].transpose(2, 0, 1)
11
+ return one_hot_seg[:num_classes]
12
+
13
+
14
+ def single_one_hot(segmentation, cls):
15
+ one_hot_seg = np.zeros_like(segmentation)
16
+ one_hot_seg[segmentation == cls] = 1
17
+ return one_hot_seg
18
+
19
+
20
+ def get_single_contiguous_segment(one_hot_segmentation):
21
+ kernel = np.ones((3, 3), dtype=one_hot_segmentation.dtype)
22
+ seg = scipy.ndimage.label(one_hot_segmentation, structure=kernel)[0]
23
+ return [np.where(seg == l) for l in range(1, seg.max() + 1)]
24
+
25
+
26
+ def get_contiguous_segments(one_hot_segmentation):
27
+ kernel = np.ones((3, 3), dtype=one_hot_segmentation.dtype)
28
+ segments_tensor = np.stack(
29
+ [scipy.ndimage.label(seg, structure=kernel)[0] for seg in one_hot_segmentation]
30
+ )
31
+
32
+ return {
33
+ c: [np.where(seg == l) for l in range(1, seg.max() + 1)]
34
+ for c, seg in enumerate(segments_tensor)
35
+ }
36
+
37
+
38
+ def get_exact_kernel(width):
39
+ x = np.arange(-width, width + 1)
40
+ xx, yy = np.meshgrid(x, x)
41
+ d = np.sqrt(xx**2 + yy**2)
42
+ kernel = (np.round(d) <= width).astype(np.uint8)
43
+ return kernel
44
+
45
+
46
+ def erode_mask(mask, width, implementation="fast"):
47
+ if mask.ndim == 2:
48
+ input_mask = mask.astype(np.uint8)
49
+ elif mask.ndim == 3:
50
+ input_mask = mask.astype(np.uint8).transpose(1, 2, 0)
51
+ else:
52
+ raise ValueError(f"Assume an array of shape (H,W) or (C,H,W), got {mask.shape}!")
53
+
54
+ if implementation == "fast":
55
+ kernel = np.ones((3, 3), dtype=np.uint8)
56
+ eroded_mask = cv2.erode(input_mask, kernel, iterations=width)
57
+ elif implementation == "exact":
58
+ kernel = get_exact_kernel(width)
59
+ eroded_mask = cv2.erode(input_mask, kernel, iterations=1)
60
+ else:
61
+ raise ValueError(
62
+ f'Implementation has to be one of "exact" and "fast", received: {implementation}!'
63
+ )
64
+
65
+ if input_mask.ndim == 2:
66
+ return eroded_mask
67
+ else: # input_mask.ndim == 3
68
+ if mask.shape[0] == 1: # in this case, the first axis gets removed by cv2
69
+ eroded_mask = np.expand_dims(eroded_mask, -1)
70
+ return eroded_mask.transpose(2, 0, 1)
71
+
72
+
73
+ def dilate_mask(mask, width, implementation="fast"):
74
+ if mask.ndim == 2:
75
+ input_mask = mask.astype(np.uint8)
76
+ elif mask.ndim == 3:
77
+ input_mask = mask.astype(np.uint8).transpose(1, 2, 0)
78
+ else:
79
+ raise ValueError(f"Assume an array of shape (H,W) or (C,H,W), got {mask.shape}!")
80
+
81
+ if implementation == "fast":
82
+ kernel = np.ones((3, 3), dtype=np.uint8)
83
+ dilated_mask = cv2.dilate(input_mask, kernel, iterations=width)
84
+ elif implementation == "exact":
85
+ kernel = get_exact_kernel(width)
86
+ dilated_mask = cv2.dilate(input_mask, kernel, iterations=1)
87
+ else:
88
+ raise ValueError(
89
+ f'Implementation has to be one of "exact" and "fast", received: {implementation}!'
90
+ )
91
+
92
+ if input_mask.ndim == 2:
93
+ return dilated_mask
94
+ else: # input_mask.ndim == 3
95
+ if mask.shape[0] == 1: # in this case, the first axis gets removed by cv2
96
+ dilated_mask = np.expand_dims(dilated_mask, -1)
97
+ return dilated_mask.transpose(2, 0, 1)
98
+
99
+
100
+ def get_interior_boundary(mask, width, implementation="fast"):
101
+ eroded_mask = erode_mask(mask, width, implementation)
102
+ boundary_mask = (mask - eroded_mask).astype(np.bool_)
103
+ return boundary_mask
104
+
105
+
106
+ def get_exterior_boundary(mask, width, implementation="fast"):
107
+ dilated_mask = dilate_mask(mask, width, implementation)
108
+ boundary_mask = (dilated_mask - mask).astype(np.bool_)
109
+ return boundary_mask
@@ -6,18 +6,18 @@ import pandas as pd
6
6
 
7
7
  from supervisely.annotation.annotation import ProjectMeta
8
8
  from supervisely.api.api import Api
9
+ from supervisely.api.module_api import ApiField
9
10
  from supervisely.api.dataset_api import DatasetInfo
10
11
  from supervisely.api.project_api import ProjectInfo
11
12
  from supervisely.app.widgets import SlyTqdm
12
13
  from supervisely.io.env import team_id
13
14
  from supervisely.io.fs import dir_empty, mkdir
14
15
  from supervisely.io.json import load_json_file
15
- from supervisely.nn.benchmark.evaluation.coco.metric_provider import MetricProvider
16
+ from supervisely.nn.benchmark.utils.detection.metric_provider import MetricProvider
16
17
  from supervisely.nn.benchmark.visualization.vis_click_data import ClickData, IdMapper
17
18
  from supervisely.sly_logger import logger
18
19
  from supervisely.task.progress import tqdm_sly
19
20
 
20
-
21
21
  # class ImageComparisonData:
22
22
  # def __init__(
23
23
  # self,
@@ -86,6 +86,14 @@ class EvalResult:
86
86
  model_name = self.inference_info.get("model_name", self.eval_dir)
87
87
  return self.inference_info.get("deploy_params", {}).get("checkpoint_name", model_name)
88
88
 
89
+ @property
90
+ def model_name(self) -> str:
91
+ if not self.name:
92
+ return
93
+ if len(self.name) > 20:
94
+ return self.name[:9] + "..." + self.name[-6:]
95
+ return self.name
96
+
89
97
  @property
90
98
  def gt_project_id(self) -> int:
91
99
  return self.inference_info.get("gt_project_id")
@@ -114,7 +122,13 @@ class EvalResult:
114
122
  if self._gt_dataset_infos is None:
115
123
  filters = None
116
124
  if self.gt_dataset_ids is not None:
117
- filters = [{"field": "id", "operator": "in", "value": self.gt_dataset_ids}]
125
+ filters = [
126
+ {
127
+ ApiField.FIELD: ApiField.ID,
128
+ ApiField.OPERATOR: "in",
129
+ ApiField.VALUE: self.gt_dataset_ids,
130
+ }
131
+ ]
118
132
  self._gt_dataset_infos = self.api.dataset.get_list(
119
133
  self.gt_project_id,
120
134
  filters=filters,
@@ -2,7 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from collections import defaultdict
4
4
 
5
- from supervisely.nn.benchmark.evaluation.coco.metric_provider import (
5
+ from supervisely.nn.benchmark.utils.detection.metric_provider import (
6
6
  MetricProvider,
7
7
  )
8
8
 
@@ -12,6 +12,9 @@ from supervisely.nn.benchmark.visualization.widgets.markdown.markdown import (
12
12
  from supervisely.nn.benchmark.visualization.widgets.notification.notification import (
13
13
  NotificationWidget,
14
14
  )
15
+ from supervisely.nn.benchmark.visualization.widgets.radio_group.radio_group import (
16
+ RadioGroupWidget,
17
+ )
15
18
  from supervisely.nn.benchmark.visualization.widgets.sidebar.sidebar import SidebarWidget
16
19
  from supervisely.nn.benchmark.visualization.widgets.table.table import TableWidget
17
20
  from supervisely.nn.benchmark.visualization.widgets.widget import BaseWidget
@@ -13,10 +13,14 @@ class ChartWidget(BaseWidget):
13
13
  self,
14
14
  name: str,
15
15
  figure, # plotly figure
16
+ switchable: bool = False,
17
+ switch_key: str = "switch_key",
18
+ radiogroup_id: str = None,
16
19
  ) -> None:
17
20
  super().__init__(name)
18
- self.radio_group = "radio_group" # TODO: fix
19
- self.switch_key = "switch_key" # TODO: fix
21
+ self.switchable = switchable
22
+ self.switch_key = switch_key
23
+ self.radiogroup_id = radiogroup_id
20
24
 
21
25
  self.figure = figure
22
26
  self.click_data = None
@@ -47,7 +51,8 @@ class ChartWidget(BaseWidget):
47
51
  def _get_template_data(self):
48
52
  return {
49
53
  "widget_id": self.id,
50
- "radio_group": self.radio_group,
54
+ "radio_group": self.radiogroup_id,
55
+ "switchable": self.switchable,
51
56
  "switch_key": self.switch_key,
52
57
  "init_data_source": self.data_source,
53
58
  "click_handled": self.click_data is not None,
@@ -69,4 +74,7 @@ class ChartWidget(BaseWidget):
69
74
  }
70
75
 
71
76
  def get_state(self) -> Dict:
72
- return {}
77
+ res = {}
78
+ if self.switchable:
79
+ res[self.radiogroup_id] = self.switch_key
80
+ return res
@@ -1,12 +1,11 @@
1
1
  import json
2
2
  from pathlib import Path
3
- from typing import List, Optional, Union
3
+ from typing import Any, List, Optional, Union
4
4
 
5
5
  from jinja2 import Template
6
6
 
7
7
  from supervisely.api.annotation_api import AnnotationInfo
8
8
  from supervisely.api.image_api import ImageInfo
9
- from supervisely.app.widgets import GridGalleryV2
10
9
  from supervisely.io.fs import ensure_base_path
11
10
  from supervisely.nn.benchmark.visualization.widgets.widget import BaseWidget
12
11
  from supervisely.project.project_meta import ProjectMeta
@@ -19,23 +18,34 @@ class GalleryWidget(BaseWidget):
19
18
  filters: Optional[List] = None,
20
19
  is_modal: Optional[bool] = False,
21
20
  columns_number: int = 3,
21
+ click_gallery_id: Optional[str] = None,
22
+ opacity: Optional[float] = 0.4,
23
+ limit: Optional[int] = None,
22
24
  ):
23
25
  super().__init__(name)
24
26
  self.reference = self.id
25
27
  self.is_modal = is_modal
26
28
  self.click_handled = False
27
- self.click_gallery_id = None
29
+ self.click_gallery_id = click_gallery_id
28
30
  self.click_data = None
29
- self.click_gallery_items_limit = None
31
+ self.click_gallery_items_limit = limit or columns_number * 3
30
32
  self.image_left_header = False
31
33
  self._project_meta = None
32
34
  self.show_all_button = False
35
+ self.show_all_gallery_id = None
36
+ self.show_all_data = None
37
+ self.show_all_data_source = f"/data/{self.name}_{self.id}_show_all_data.json"
33
38
  self.columns_number = columns_number
39
+ self.get_key = None
40
+ self.opacity = opacity or 0.4
34
41
 
35
42
  filters = filters # or [{"confidence": [0.6, 1]}]
43
+
44
+ from supervisely.app.widgets import GridGalleryV2
45
+
36
46
  self._gallery = GridGalleryV2(
37
47
  columns_number=columns_number,
38
- annotations_opacity=0.4,
48
+ annotations_opacity=self.opacity,
39
49
  border_width=4,
40
50
  enable_zoom=False,
41
51
  default_tag_filters=filters,
@@ -94,6 +104,12 @@ class GalleryWidget(BaseWidget):
94
104
  with open(basepath + self.click_data_source, "w") as f:
95
105
  json.dump(self.click_data, f)
96
106
 
107
+ # show all data
108
+ if self.show_all_data is not None:
109
+ ensure_base_path(basepath + self.show_all_data_source)
110
+ with open(basepath + self.show_all_data_source, "w") as f:
111
+ json.dump(self.show_all_data, f)
112
+
97
113
  def get_state(self) -> None:
98
114
  return {}
99
115
 
@@ -101,11 +117,19 @@ class GalleryWidget(BaseWidget):
101
117
  template_str = Path(__file__).parent / "template.html"
102
118
  return Template(template_str.read_text()).render(self._get_template_data())
103
119
 
104
- def add_on_click(self, gallery_id, click_data, gallery_items_limit):
120
+ def set_click_data(
121
+ self, click_gallery_id: str, click_data: Any, get_key: Optional[str] = None
122
+ ) -> None:
105
123
  self.click_handled = True
106
- self.click_gallery_id = gallery_id
107
124
  self.click_data = click_data
108
- self.click_gallery_items_limit = gallery_items_limit
125
+ self.click_gallery_id = click_gallery_id
126
+ if get_key is not None:
127
+ self.get_key = get_key
128
+
129
+ def set_show_all_data(self, gallery_id: str, data: str) -> None:
130
+ self.show_all_button = True
131
+ self.show_all_gallery_id = gallery_id
132
+ self.show_all_data = data
109
133
 
110
134
  def add_image_left_header(self, html: str):
111
135
  self.image_left_header = html
@@ -118,8 +142,11 @@ class GalleryWidget(BaseWidget):
118
142
  "is_modal": str(self.is_modal).lower(),
119
143
  "click_handled": self.click_handled,
120
144
  "show_all_button": self.show_all_button,
145
+ "show_all_gallery_id": self.show_all_gallery_id,
146
+ "show_all_data_source": self.show_all_data_source,
121
147
  "click_data_source": self.click_data_source,
122
148
  "click_gallery_id": self.click_gallery_id,
123
149
  "click_gallery_items_limit": self.click_gallery_items_limit,
124
150
  "image_left_header": self.image_left_header,
151
+ "get_key": self.get_key,
125
152
  }
@@ -1,4 +1,4 @@
1
- <div style="position: relative; max-height: 600px; overflow: hidden;">
1
+ <div style="position: relative; max-height: 700px; overflow: hidden;">
2
2
  <sly-iw-gallery ref="{{ widget_id }}" iw-widget-id="{{ widget_id }}" :options="{'isModalWindow': {{ is_modal }}}"
3
3
  :actions="{
4
4
  'init': {
@@ -6,10 +6,14 @@
6
6
  },
7
7
  {% if click_handled %}
8
8
  'chart-click': {
9
- 'key': 'explore',
10
9
  'dataSource': '{{ click_data_source }}',
11
10
  'galleryId': '{{ click_gallery_id }}',
12
11
  'limit': {{ click_gallery_items_limit }},
12
+ {% if get_key %}
13
+ 'getKey': {{ get_key }},
14
+ {% else %}
15
+ 'key' : 'explore',
16
+ {% endif %}
13
17
  },
14
18
  {% endif %}
15
19
  }" :command="command" :data="data">
@@ -38,9 +42,9 @@
38
42
  data: {
39
43
  'key': 'explore',
40
44
  'limit': {{ click_gallery_items_limit}},
41
- 'dataSource': '{{ click_data_source }}',
45
+ 'dataSource': '{{ show_all_data_source }}',
42
46
  },
43
- 'galleryId': '{{ click_gallery_id }}',
47
+ 'galleryId': '{{ show_all_gallery_id }}',
44
48
  },
45
49
  internalCommand: true
46
50
  })">Explore more</el-button>
@@ -33,7 +33,7 @@ class MarkdownWidget(BaseWidget):
33
33
  if self.is_info_block:
34
34
  style_class += " overview-info-block"
35
35
  if self.width_fit_content:
36
- style_class += " markdown-fit-content"
36
+ style_class += " width-fit-content"
37
37
 
38
38
  return f"""
39
39
  <div style="margin-top: 10px;">
@@ -21,18 +21,22 @@ class NotificationWidget(BaseWidget):
21
21
  return {}
22
22
 
23
23
  def to_html(self) -> str:
24
- return f"""
24
+ res = f"""
25
25
  <div style="margin-top: 20px; margin-bottom: 20px;">
26
26
  <sly-iw-notification
27
27
  iw-widget-id="{ self.id }"
28
- >
28
+ >"""
29
+ if self.title:
30
+ res += f"""
29
31
  <span slot="title">
30
32
  { self.title }
31
- </span>
32
-
33
+ </span>"""
34
+ if self.desc:
35
+ res += f"""
33
36
  <span slot="description">
34
37
  { self.desc }
35
- </span>
38
+ </span>"""
39
+ res += """
36
40
  </sly-iw-notification>
37
- </div>
38
- """
41
+ </div>"""
42
+ return res
@@ -0,0 +1,34 @@
1
+ from typing import Dict, List
2
+
3
+ from supervisely.nn.benchmark.visualization.widgets.widget import BaseWidget
4
+
5
+
6
+ class RadioGroupWidget(BaseWidget):
7
+
8
+ def __init__(
9
+ self,
10
+ name: str,
11
+ radio_group: str,
12
+ switch_keys: List[str],
13
+ default_key: str = None,
14
+ ) -> None:
15
+ super().__init__(name)
16
+ self.radio_group = radio_group
17
+ self.switch_keys = switch_keys
18
+ self.default_key = default_key or switch_keys[0]
19
+
20
+ def save_data(self, basepath: str) -> None:
21
+ return
22
+
23
+ def get_state(self) -> Dict:
24
+ return {self.radio_group: self.default_key}
25
+
26
+ def to_html(self) -> str:
27
+ res = ""
28
+ for switch_key in self.switch_keys:
29
+ res += f"""
30
+ <el-radio v-model="state.{self.radio_group}" label="{switch_key}" style="margin-top: 10px;">
31
+ {switch_key}
32
+ </el-radio>
33
+ """
34
+ return res
@@ -13,7 +13,7 @@ class TableWidget(BaseWidget):
13
13
  name: str,
14
14
  data: Dict = None,
15
15
  click_data: Any = None,
16
- click_gellery_id: str = "",
16
+ click_gallery_id: str = "",
17
17
  fix_columns: int = 0,
18
18
  show_header_controls: bool = True,
19
19
  main_column: Optional[str] = None,
@@ -26,7 +26,7 @@ class TableWidget(BaseWidget):
26
26
  self.show_header_controls = show_header_controls
27
27
  self.main_column = main_column
28
28
  self.click_data = click_data
29
- self.click_gellery_id = click_gellery_id
29
+ self.click_gallery_id = click_gallery_id
30
30
 
31
31
  if isinstance(width, int):
32
32
  width = f"width: {width}px"
@@ -54,6 +54,12 @@ class TableWidget(BaseWidget):
54
54
  def get_state(self) -> Dict:
55
55
  return {}
56
56
 
57
+ def set_click_data(self, click_gallery_id: str, click_data: Any) -> None:
58
+ self.click_handled = True
59
+ self.click_data = click_data
60
+ self.clickable = True
61
+ self.click_gallery_id = click_gallery_id
62
+
57
63
  def get_render_data(self) -> Dict:
58
64
  return {
59
65
  "widget_id": self.id,
@@ -61,7 +67,7 @@ class TableWidget(BaseWidget):
61
67
  "showHeaderControls": self.show_header_controls,
62
68
  "init_data_source": self.data_source,
63
69
  "table_click_data": self.click_data_source,
64
- "table_gallery_id": self.click_gellery_id,
70
+ "table_gallery_id": self.click_gallery_id,
65
71
  "mainColumn": self.main_column,
66
72
  "clickable": self.clickable,
67
73
  "width": self.width or "",
@@ -11,6 +11,7 @@ class BaseWidget:
11
11
  self.title = title
12
12
  self.data_source = f"/data/{self.name}_{self.id}.json"
13
13
  self.click_data_source = f"/data/{self.name}_{self.id}_click_data.json"
14
+ self.switchable = False
14
15
 
15
16
  def save_data(self, basepath: str) -> None:
16
17
  raise NotImplementedError
@@ -20,3 +21,6 @@ class BaseWidget:
20
21
 
21
22
  def to_html(self) -> str:
22
23
  raise NotImplementedError
24
+
25
+ def set_click_data(self, click_gallery_id, click_data) -> None:
26
+ return
@@ -40,6 +40,7 @@ from supervisely.io.fs import (
40
40
  copy_file,
41
41
  copy_file_async,
42
42
  dir_empty,
43
+ file_exists,
43
44
  dir_exists,
44
45
  ensure_base_path,
45
46
  get_file_name_with_ext,
@@ -2281,6 +2282,8 @@ class Project:
2281
2282
  target_classes: Optional[List[str]] = None,
2282
2283
  progress_cb: Optional[Union[tqdm, Callable]] = None,
2283
2284
  segmentation_type: Optional[str] = "semantic",
2285
+ bg_name: Optional[str] = "__bg__",
2286
+ bg_color: Optional[List[int]] = None,
2284
2287
  ) -> None:
2285
2288
  """
2286
2289
  Makes a copy of the :class:`Project<Project>`, converts annotations to
@@ -2296,13 +2299,17 @@ class Project:
2296
2299
  :param inplace: Modifies source project If True. Must be False If dst_project_dir is specified.
2297
2300
  :type inplace: :class:`bool`, optional
2298
2301
  :param target_classes: Classes list to include to destination project. If segmentation_type="semantic",
2299
- background class "__bg__" will be added automatically.
2302
+ background class will be added automatically (by default "__bg__").
2300
2303
  :type target_classes: :class:`list` [ :class:`str` ], optional
2301
2304
  :param progress_cb: Function for tracking download progress.
2302
2305
  :type progress_cb: tqdm or callable, optional
2303
- :param segmentation_type: One of: {"semantic", "instance"}. If segmentation_type="semantic", background class "__bg__"
2304
- will be added automatically and instances will be converted to non overlapping semantic segmentation mask.
2306
+ :param segmentation_type: One of: {"semantic", "instance"}. If segmentation_type="semantic", background class
2307
+ will be added automatically (by default "__bg__") and instances will be converted to non overlapping semantic segmentation mask.
2305
2308
  :type segmentation_type: :class:`str`
2309
+ :param bg_name: Default background class name, used for semantic segmentation.
2310
+ :type bg_name: :class:`str`, optional
2311
+ :param bg_color: Default background class color, used for semantic segmentation.
2312
+ :type bg_color: :class:`list`, optional. Default is [0, 0, 0]
2306
2313
  :return: None
2307
2314
  :rtype: NoneType
2308
2315
  :Usage example:
@@ -2319,8 +2326,9 @@ class Project:
2319
2326
  seg_project = sly.Project(seg_project_path, sly.OpenMode.READ)
2320
2327
  """
2321
2328
 
2322
- _bg_class_name = "__bg__"
2323
- _bg_obj_class = ObjClass(_bg_class_name, Bitmap, color=[0, 0, 0])
2329
+ _bg_class_name = bg_name
2330
+ bg_color = bg_color or [0, 0, 0]
2331
+ _bg_obj_class = ObjClass(_bg_class_name, Bitmap, color=bg_color)
2324
2332
 
2325
2333
  if dst_project_dir is None and inplace is False:
2326
2334
  raise ValueError(
@@ -2388,7 +2396,11 @@ class Project:
2388
2396
 
2389
2397
  seg_path = None
2390
2398
  if inplace is False:
2391
- dst_dataset.add_item_file(item_name, img_path, seg_ann)
2399
+ if file_exists(img_path):
2400
+ dst_dataset.add_item_file(item_name, img_path, seg_ann)
2401
+ else:
2402
+ # if local project has no images
2403
+ dst_dataset._add_ann_by_type(item_name, seg_ann)
2392
2404
  seg_path = dst_dataset.get_seg_path(item_name)
2393
2405
  else:
2394
2406
  # replace existing annotation
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.238
3
+ Version: 6.73.240
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -105,6 +105,8 @@ Provides-Extra: model-benchmark
105
105
  Requires-Dist: pycocotools; extra == "model-benchmark"
106
106
  Requires-Dist: scikit-learn; extra == "model-benchmark"
107
107
  Requires-Dist: plotly==5.22.0; extra == "model-benchmark"
108
+ Requires-Dist: torch==1.13.0; extra == "model-benchmark"
109
+ Requires-Dist: torchvision==0.14.0; extra == "model-benchmark"
108
110
  Provides-Extra: plugins
109
111
  Requires-Dist: jsonschema<3.0.0,>=2.6.0; extra == "plugins"
110
112
  Provides-Extra: sdk-nn-plugins