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.
- supervisely/annotation/annotation.py +2 -2
- supervisely/api/entity_annotation/tag_api.py +11 -4
- supervisely/api/file_api.py +17 -3
- supervisely/nn/__init__.py +1 -0
- supervisely/nn/benchmark/__init__.py +14 -2
- supervisely/nn/benchmark/base_benchmark.py +84 -37
- supervisely/nn/benchmark/base_evaluator.py +120 -0
- supervisely/nn/benchmark/base_visualizer.py +265 -0
- supervisely/nn/benchmark/comparison/detection_visualization/text_templates.py +5 -5
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/calibration_score.py +2 -2
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/explore_predicttions.py +39 -16
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/localization_accuracy.py +1 -1
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/outcome_counts.py +4 -4
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/overview.py +12 -11
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/pr_curve.py +1 -1
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/precision_recal_f1.py +6 -6
- supervisely/nn/benchmark/comparison/detection_visualization/vis_metrics/speedtest.py +3 -3
- supervisely/nn/benchmark/{instance_segmentation_benchmark.py → instance_segmentation/benchmark.py} +9 -3
- supervisely/nn/benchmark/instance_segmentation/evaluator.py +58 -0
- supervisely/nn/benchmark/{visualization/text_templates/instance_segmentation_text.py → instance_segmentation/text_templates.py} +53 -69
- supervisely/nn/benchmark/instance_segmentation/visualizer.py +18 -0
- supervisely/nn/benchmark/object_detection/__init__.py +0 -0
- supervisely/nn/benchmark/object_detection/base_vis_metric.py +51 -0
- supervisely/nn/benchmark/{object_detection_benchmark.py → object_detection/benchmark.py} +4 -2
- supervisely/nn/benchmark/object_detection/evaluation_params.yaml +2 -0
- supervisely/nn/benchmark/{evaluation/object_detection_evaluator.py → object_detection/evaluator.py} +67 -9
- supervisely/nn/benchmark/{evaluation/coco → object_detection}/metric_provider.py +13 -14
- supervisely/nn/benchmark/{visualization/text_templates/object_detection_text.py → object_detection/text_templates.py} +49 -41
- supervisely/nn/benchmark/object_detection/vis_metrics/__init__.py +48 -0
- supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/confidence_distribution.py +20 -24
- supervisely/nn/benchmark/object_detection/vis_metrics/confidence_score.py +119 -0
- supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/confusion_matrix.py +34 -22
- supervisely/nn/benchmark/object_detection/vis_metrics/explore_predictions.py +129 -0
- supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/f1_score_at_different_iou.py +21 -26
- supervisely/nn/benchmark/object_detection/vis_metrics/frequently_confused.py +137 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/iou_distribution.py +106 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/key_metrics.py +136 -0
- supervisely/nn/benchmark/{visualization → object_detection}/vis_metrics/model_predictions.py +53 -49
- supervisely/nn/benchmark/object_detection/vis_metrics/outcome_counts.py +188 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/outcome_counts_per_class.py +191 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/overview.py +116 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve.py +106 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve_by_class.py +49 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/precision.py +72 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/precision_avg_per_class.py +59 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/recall.py +71 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/recall_vs_precision.py +56 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/reliability_diagram.py +110 -0
- supervisely/nn/benchmark/object_detection/vis_metrics/speedtest.py +151 -0
- supervisely/nn/benchmark/object_detection/visualizer.py +697 -0
- supervisely/nn/benchmark/semantic_segmentation/__init__.py +9 -0
- supervisely/nn/benchmark/semantic_segmentation/base_vis_metric.py +55 -0
- supervisely/nn/benchmark/semantic_segmentation/benchmark.py +32 -0
- supervisely/nn/benchmark/semantic_segmentation/evaluation_params.yaml +0 -0
- supervisely/nn/benchmark/semantic_segmentation/evaluator.py +162 -0
- supervisely/nn/benchmark/semantic_segmentation/metric_provider.py +153 -0
- supervisely/nn/benchmark/semantic_segmentation/text_templates.py +130 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/__init__.py +0 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/acknowledgement.py +15 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/classwise_error_analysis.py +57 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/confusion_matrix.py +92 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/explore_predictions.py +84 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/frequently_confused.py +101 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/iou_eou.py +45 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/key_metrics.py +60 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/model_predictions.py +107 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/overview.py +112 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/renormalized_error_ou.py +48 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/speedtest.py +178 -0
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/vis_texts.py +21 -0
- supervisely/nn/benchmark/semantic_segmentation/visualizer.py +304 -0
- supervisely/nn/benchmark/utils/__init__.py +12 -0
- supervisely/nn/benchmark/utils/detection/__init__.py +2 -0
- supervisely/nn/benchmark/{evaluation/coco → utils/detection}/calculate_metrics.py +6 -4
- supervisely/nn/benchmark/utils/detection/metric_provider.py +533 -0
- supervisely/nn/benchmark/{coco_utils → utils/detection}/sly2coco.py +4 -4
- supervisely/nn/benchmark/{coco_utils/utils.py → utils/detection/utlis.py} +11 -0
- supervisely/nn/benchmark/utils/semantic_segmentation/__init__.py +0 -0
- supervisely/nn/benchmark/utils/semantic_segmentation/calculate_metrics.py +35 -0
- supervisely/nn/benchmark/utils/semantic_segmentation/evaluator.py +804 -0
- supervisely/nn/benchmark/utils/semantic_segmentation/loader.py +65 -0
- supervisely/nn/benchmark/utils/semantic_segmentation/utils.py +109 -0
- supervisely/nn/benchmark/visualization/evaluation_result.py +17 -3
- supervisely/nn/benchmark/visualization/vis_click_data.py +1 -1
- supervisely/nn/benchmark/visualization/widgets/__init__.py +3 -0
- supervisely/nn/benchmark/visualization/widgets/chart/chart.py +12 -4
- supervisely/nn/benchmark/visualization/widgets/gallery/gallery.py +35 -8
- supervisely/nn/benchmark/visualization/widgets/gallery/template.html +8 -4
- supervisely/nn/benchmark/visualization/widgets/markdown/markdown.py +1 -1
- supervisely/nn/benchmark/visualization/widgets/notification/notification.py +11 -7
- supervisely/nn/benchmark/visualization/widgets/radio_group/__init__.py +0 -0
- supervisely/nn/benchmark/visualization/widgets/radio_group/radio_group.py +34 -0
- supervisely/nn/benchmark/visualization/widgets/table/table.py +9 -3
- supervisely/nn/benchmark/visualization/widgets/widget.py +4 -0
- supervisely/project/project.py +18 -6
- {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/METADATA +3 -1
- {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/RECORD +104 -82
- supervisely/nn/benchmark/coco_utils/__init__.py +0 -2
- supervisely/nn/benchmark/evaluation/__init__.py +0 -3
- supervisely/nn/benchmark/evaluation/base_evaluator.py +0 -64
- supervisely/nn/benchmark/evaluation/coco/__init__.py +0 -2
- supervisely/nn/benchmark/evaluation/instance_segmentation_evaluator.py +0 -88
- supervisely/nn/benchmark/utils.py +0 -13
- supervisely/nn/benchmark/visualization/inference_speed/__init__.py +0 -19
- supervisely/nn/benchmark/visualization/inference_speed/speedtest_batch.py +0 -161
- supervisely/nn/benchmark/visualization/inference_speed/speedtest_intro.py +0 -28
- supervisely/nn/benchmark/visualization/inference_speed/speedtest_overview.py +0 -141
- supervisely/nn/benchmark/visualization/inference_speed/speedtest_real_time.py +0 -63
- supervisely/nn/benchmark/visualization/text_templates/inference_speed_text.py +0 -23
- supervisely/nn/benchmark/visualization/vis_metric_base.py +0 -337
- supervisely/nn/benchmark/visualization/vis_metrics/__init__.py +0 -67
- supervisely/nn/benchmark/visualization/vis_metrics/classwise_error_analysis.py +0 -55
- supervisely/nn/benchmark/visualization/vis_metrics/confidence_score.py +0 -93
- supervisely/nn/benchmark/visualization/vis_metrics/explorer_grid.py +0 -144
- supervisely/nn/benchmark/visualization/vis_metrics/frequently_confused.py +0 -115
- supervisely/nn/benchmark/visualization/vis_metrics/iou_distribution.py +0 -86
- supervisely/nn/benchmark/visualization/vis_metrics/outcome_counts.py +0 -119
- supervisely/nn/benchmark/visualization/vis_metrics/outcome_counts_per_class.py +0 -148
- supervisely/nn/benchmark/visualization/vis_metrics/overall_error_analysis.py +0 -109
- supervisely/nn/benchmark/visualization/vis_metrics/overview.py +0 -189
- supervisely/nn/benchmark/visualization/vis_metrics/percision_avg_per_class.py +0 -57
- supervisely/nn/benchmark/visualization/vis_metrics/pr_curve.py +0 -101
- supervisely/nn/benchmark/visualization/vis_metrics/pr_curve_by_class.py +0 -46
- supervisely/nn/benchmark/visualization/vis_metrics/precision.py +0 -56
- supervisely/nn/benchmark/visualization/vis_metrics/recall.py +0 -54
- supervisely/nn/benchmark/visualization/vis_metrics/recall_vs_precision.py +0 -57
- supervisely/nn/benchmark/visualization/vis_metrics/reliability_diagram.py +0 -88
- supervisely/nn/benchmark/visualization/vis_metrics/what_is.py +0 -23
- supervisely/nn/benchmark/visualization/vis_templates.py +0 -241
- supervisely/nn/benchmark/visualization/vis_widgets.py +0 -128
- supervisely/nn/benchmark/visualization/visualizer.py +0 -729
- /supervisely/nn/benchmark/{visualization/text_templates → instance_segmentation}/__init__.py +0 -0
- /supervisely/nn/benchmark/{evaluation/coco → instance_segmentation}/evaluation_params.yaml +0 -0
- /supervisely/nn/benchmark/{evaluation/coco → utils/detection}/metrics.py +0 -0
- {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/LICENSE +0 -0
- {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/WHEEL +0 -0
- {supervisely-6.73.238.dist-info → supervisely-6.73.240.dist-info}/entry_points.txt +0 -0
- {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.
|
|
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 = [
|
|
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,
|
|
@@ -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.
|
|
19
|
-
self.switch_key =
|
|
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.
|
|
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
|
-
|
|
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 =
|
|
29
|
+
self.click_gallery_id = click_gallery_id
|
|
28
30
|
self.click_data = None
|
|
29
|
-
self.click_gallery_items_limit =
|
|
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=
|
|
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
|
|
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.
|
|
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:
|
|
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': '{{
|
|
45
|
+
'dataSource': '{{ show_all_data_source }}',
|
|
42
46
|
},
|
|
43
|
-
'galleryId': '{{
|
|
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 += "
|
|
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
|
-
|
|
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
|
|
File without changes
|
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
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
|
supervisely/project/project.py
CHANGED
|
@@ -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
|
|
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
|
|
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 =
|
|
2323
|
-
|
|
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
|
-
|
|
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.
|
|
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
|