supervisely 6.73.438__py3-none-any.whl → 6.73.513__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/__init__.py +137 -1
- supervisely/_utils.py +81 -0
- supervisely/annotation/annotation.py +8 -2
- supervisely/annotation/json_geometries_map.py +14 -11
- supervisely/annotation/label.py +80 -3
- supervisely/api/annotation_api.py +14 -11
- supervisely/api/api.py +59 -38
- supervisely/api/app_api.py +11 -2
- supervisely/api/dataset_api.py +74 -12
- supervisely/api/entities_collection_api.py +10 -0
- supervisely/api/entity_annotation/figure_api.py +52 -4
- supervisely/api/entity_annotation/object_api.py +3 -3
- supervisely/api/entity_annotation/tag_api.py +63 -12
- supervisely/api/guides_api.py +210 -0
- supervisely/api/image_api.py +72 -1
- supervisely/api/labeling_job_api.py +83 -1
- supervisely/api/labeling_queue_api.py +33 -7
- supervisely/api/module_api.py +9 -0
- supervisely/api/project_api.py +71 -26
- supervisely/api/storage_api.py +3 -1
- supervisely/api/task_api.py +13 -2
- supervisely/api/team_api.py +4 -3
- supervisely/api/video/video_annotation_api.py +119 -3
- supervisely/api/video/video_api.py +65 -14
- supervisely/api/video/video_figure_api.py +24 -11
- supervisely/app/__init__.py +1 -1
- supervisely/app/content.py +23 -7
- supervisely/app/development/development.py +18 -2
- supervisely/app/fastapi/__init__.py +1 -0
- supervisely/app/fastapi/custom_static_files.py +1 -1
- supervisely/app/fastapi/multi_user.py +105 -0
- supervisely/app/fastapi/subapp.py +88 -42
- supervisely/app/fastapi/websocket.py +77 -9
- supervisely/app/singleton.py +21 -0
- supervisely/app/v1/app_service.py +18 -2
- supervisely/app/v1/constants.py +7 -1
- supervisely/app/widgets/__init__.py +6 -0
- supervisely/app/widgets/activity_feed/__init__.py +0 -0
- supervisely/app/widgets/activity_feed/activity_feed.py +239 -0
- supervisely/app/widgets/activity_feed/style.css +78 -0
- supervisely/app/widgets/activity_feed/template.html +22 -0
- supervisely/app/widgets/card/card.py +20 -0
- supervisely/app/widgets/classes_list_selector/classes_list_selector.py +121 -9
- supervisely/app/widgets/classes_list_selector/template.html +60 -93
- supervisely/app/widgets/classes_mapping/classes_mapping.py +13 -12
- supervisely/app/widgets/classes_table/classes_table.py +1 -0
- supervisely/app/widgets/deploy_model/deploy_model.py +56 -35
- supervisely/app/widgets/dialog/dialog.py +12 -0
- supervisely/app/widgets/dialog/template.html +2 -1
- supervisely/app/widgets/ecosystem_model_selector/ecosystem_model_selector.py +1 -1
- supervisely/app/widgets/experiment_selector/experiment_selector.py +8 -0
- supervisely/app/widgets/fast_table/fast_table.py +184 -60
- supervisely/app/widgets/fast_table/template.html +1 -1
- supervisely/app/widgets/heatmap/__init__.py +0 -0
- supervisely/app/widgets/heatmap/heatmap.py +564 -0
- supervisely/app/widgets/heatmap/script.js +533 -0
- supervisely/app/widgets/heatmap/style.css +233 -0
- supervisely/app/widgets/heatmap/template.html +21 -0
- supervisely/app/widgets/modal/__init__.py +0 -0
- supervisely/app/widgets/modal/modal.py +198 -0
- supervisely/app/widgets/modal/template.html +10 -0
- supervisely/app/widgets/object_class_view/object_class_view.py +3 -0
- supervisely/app/widgets/radio_tabs/radio_tabs.py +18 -2
- supervisely/app/widgets/radio_tabs/template.html +1 -0
- supervisely/app/widgets/select/select.py +6 -3
- supervisely/app/widgets/select_class/__init__.py +0 -0
- supervisely/app/widgets/select_class/select_class.py +363 -0
- supervisely/app/widgets/select_class/template.html +50 -0
- supervisely/app/widgets/select_cuda/select_cuda.py +22 -0
- supervisely/app/widgets/select_dataset_tree/select_dataset_tree.py +65 -7
- supervisely/app/widgets/select_tag/__init__.py +0 -0
- supervisely/app/widgets/select_tag/select_tag.py +352 -0
- supervisely/app/widgets/select_tag/template.html +64 -0
- supervisely/app/widgets/select_team/select_team.py +37 -4
- supervisely/app/widgets/select_team/template.html +4 -5
- supervisely/app/widgets/select_user/__init__.py +0 -0
- supervisely/app/widgets/select_user/select_user.py +270 -0
- supervisely/app/widgets/select_user/template.html +13 -0
- supervisely/app/widgets/select_workspace/select_workspace.py +59 -10
- supervisely/app/widgets/select_workspace/template.html +9 -12
- supervisely/app/widgets/table/table.py +68 -13
- supervisely/app/widgets/tree_select/tree_select.py +2 -0
- supervisely/aug/aug.py +6 -2
- supervisely/convert/base_converter.py +1 -0
- supervisely/convert/converter.py +2 -2
- supervisely/convert/image/csv/csv_converter.py +24 -15
- supervisely/convert/image/image_converter.py +3 -1
- supervisely/convert/image/image_helper.py +48 -4
- supervisely/convert/image/label_studio/label_studio_converter.py +2 -0
- supervisely/convert/image/medical2d/medical2d_helper.py +2 -24
- supervisely/convert/image/multispectral/multispectral_converter.py +6 -0
- supervisely/convert/image/pascal_voc/pascal_voc_converter.py +8 -5
- supervisely/convert/image/pascal_voc/pascal_voc_helper.py +7 -0
- supervisely/convert/pointcloud/kitti_3d/kitti_3d_converter.py +33 -3
- supervisely/convert/pointcloud/kitti_3d/kitti_3d_helper.py +12 -5
- supervisely/convert/pointcloud/las/las_converter.py +13 -1
- supervisely/convert/pointcloud/las/las_helper.py +110 -11
- supervisely/convert/pointcloud/nuscenes_conv/nuscenes_converter.py +27 -16
- supervisely/convert/pointcloud/pointcloud_converter.py +91 -3
- supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_converter.py +58 -22
- supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_helper.py +21 -47
- supervisely/convert/video/__init__.py +1 -0
- supervisely/convert/video/multi_view/__init__.py +0 -0
- supervisely/convert/video/multi_view/multi_view.py +543 -0
- supervisely/convert/video/sly/sly_video_converter.py +359 -3
- supervisely/convert/video/video_converter.py +24 -4
- supervisely/convert/volume/dicom/dicom_converter.py +13 -5
- supervisely/convert/volume/dicom/dicom_helper.py +30 -18
- supervisely/geometry/constants.py +1 -0
- supervisely/geometry/geometry.py +4 -0
- supervisely/geometry/helpers.py +5 -1
- supervisely/geometry/oriented_bbox.py +676 -0
- supervisely/geometry/polyline_3d.py +110 -0
- supervisely/geometry/rectangle.py +2 -1
- supervisely/io/env.py +76 -1
- supervisely/io/fs.py +21 -0
- supervisely/nn/benchmark/base_evaluator.py +104 -11
- supervisely/nn/benchmark/instance_segmentation/evaluator.py +1 -8
- supervisely/nn/benchmark/object_detection/evaluator.py +20 -4
- supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve.py +10 -5
- supervisely/nn/benchmark/semantic_segmentation/evaluator.py +34 -16
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/confusion_matrix.py +1 -1
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/frequently_confused.py +1 -1
- supervisely/nn/benchmark/semantic_segmentation/vis_metrics/overview.py +1 -1
- supervisely/nn/benchmark/visualization/evaluation_result.py +66 -4
- supervisely/nn/inference/cache.py +43 -18
- supervisely/nn/inference/gui/serving_gui_template.py +5 -2
- supervisely/nn/inference/inference.py +916 -222
- supervisely/nn/inference/inference_request.py +55 -10
- supervisely/nn/inference/predict_app/gui/classes_selector.py +83 -12
- supervisely/nn/inference/predict_app/gui/gui.py +676 -488
- supervisely/nn/inference/predict_app/gui/input_selector.py +205 -26
- supervisely/nn/inference/predict_app/gui/model_selector.py +2 -4
- supervisely/nn/inference/predict_app/gui/output_selector.py +46 -6
- supervisely/nn/inference/predict_app/gui/settings_selector.py +756 -59
- supervisely/nn/inference/predict_app/gui/tags_selector.py +1 -1
- supervisely/nn/inference/predict_app/gui/utils.py +236 -119
- supervisely/nn/inference/predict_app/predict_app.py +2 -2
- supervisely/nn/inference/session.py +43 -35
- supervisely/nn/inference/tracking/bbox_tracking.py +118 -35
- supervisely/nn/inference/tracking/point_tracking.py +5 -1
- supervisely/nn/inference/tracking/tracker_interface.py +10 -1
- supervisely/nn/inference/uploader.py +139 -12
- supervisely/nn/live_training/__init__.py +7 -0
- supervisely/nn/live_training/api_server.py +111 -0
- supervisely/nn/live_training/artifacts_utils.py +243 -0
- supervisely/nn/live_training/checkpoint_utils.py +229 -0
- supervisely/nn/live_training/dynamic_sampler.py +44 -0
- supervisely/nn/live_training/helpers.py +14 -0
- supervisely/nn/live_training/incremental_dataset.py +146 -0
- supervisely/nn/live_training/live_training.py +497 -0
- supervisely/nn/live_training/loss_plateau_detector.py +111 -0
- supervisely/nn/live_training/request_queue.py +52 -0
- supervisely/nn/model/model_api.py +9 -0
- supervisely/nn/model/prediction.py +2 -1
- supervisely/nn/model/prediction_session.py +26 -14
- supervisely/nn/prediction_dto.py +19 -1
- supervisely/nn/tracker/base_tracker.py +11 -1
- supervisely/nn/tracker/botsort/botsort_config.yaml +0 -1
- supervisely/nn/tracker/botsort/tracker/mc_bot_sort.py +7 -4
- supervisely/nn/tracker/botsort_tracker.py +94 -65
- supervisely/nn/tracker/utils.py +4 -5
- supervisely/nn/tracker/visualize.py +93 -93
- supervisely/nn/training/gui/classes_selector.py +16 -1
- supervisely/nn/training/gui/train_val_splits_selector.py +52 -31
- supervisely/nn/training/train_app.py +46 -31
- supervisely/project/data_version.py +115 -51
- supervisely/project/download.py +1 -1
- supervisely/project/pointcloud_episode_project.py +37 -8
- supervisely/project/pointcloud_project.py +30 -2
- supervisely/project/project.py +14 -2
- supervisely/project/project_meta.py +27 -1
- supervisely/project/project_settings.py +32 -18
- supervisely/project/versioning/__init__.py +1 -0
- supervisely/project/versioning/common.py +20 -0
- supervisely/project/versioning/schema_fields.py +35 -0
- supervisely/project/versioning/video_schema.py +221 -0
- supervisely/project/versioning/volume_schema.py +87 -0
- supervisely/project/video_project.py +717 -15
- supervisely/project/volume_project.py +623 -5
- supervisely/template/experiment/experiment.html.jinja +4 -4
- supervisely/template/experiment/experiment_generator.py +14 -21
- supervisely/template/live_training/__init__.py +0 -0
- supervisely/template/live_training/header.html.jinja +96 -0
- supervisely/template/live_training/live_training.html.jinja +51 -0
- supervisely/template/live_training/live_training_generator.py +464 -0
- supervisely/template/live_training/sly-style.css +402 -0
- supervisely/template/live_training/template.html.jinja +18 -0
- supervisely/versions.json +28 -26
- supervisely/video/sampling.py +39 -20
- supervisely/video/video.py +41 -12
- supervisely/video_annotation/video_figure.py +38 -4
- supervisely/video_annotation/video_object.py +29 -4
- supervisely/volume/stl_converter.py +2 -0
- supervisely/worker_api/agent_rpc.py +24 -1
- supervisely/worker_api/rpc_servicer.py +31 -7
- {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/METADATA +58 -40
- {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/RECORD +203 -155
- {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/WHEEL +1 -1
- supervisely_lib/__init__.py +6 -1
- {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info/licenses}/LICENSE +0 -0
- {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/top_level.txt +0 -0
|
@@ -5,23 +5,19 @@ import time
|
|
|
5
5
|
import traceback
|
|
6
6
|
import uuid
|
|
7
7
|
from concurrent.futures import Future, ThreadPoolExecutor
|
|
8
|
-
from functools import partial
|
|
8
|
+
from functools import partial
|
|
9
9
|
from typing import Any, Dict, List, Tuple, Union
|
|
10
10
|
|
|
11
|
-
from supervisely._utils import rand_str
|
|
12
11
|
from supervisely.nn.utils import get_gpu_usage, get_ram_usage
|
|
13
12
|
from supervisely.sly_logger import logger
|
|
14
13
|
from supervisely.task.progress import Progress
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
def generate_uuid(self) -> str:
|
|
18
|
-
"""
|
|
19
|
-
Generates a unique UUID for the inference request.
|
|
20
|
-
"""
|
|
21
|
-
return uuid.uuid5(namespace=uuid.NAMESPACE_URL, name=f"{time.time()}-{rand_str(10)}").hex
|
|
22
|
-
|
|
23
|
-
|
|
24
16
|
class InferenceRequest:
|
|
17
|
+
PAUSE_SLEEP_INTERVAL = 1.0
|
|
18
|
+
PAUSE_SLEEP_MAX_WAIT = 60 * 60 # 1 hour
|
|
19
|
+
PENDING_RESULTS_MAX_SIZE = 500
|
|
20
|
+
|
|
25
21
|
class Stage:
|
|
26
22
|
PREPARING = "Preparing model for inference..."
|
|
27
23
|
INFERENCE = "Running inference..."
|
|
@@ -47,6 +43,10 @@ class InferenceRequest:
|
|
|
47
43
|
self._final_result = None
|
|
48
44
|
self._exception = None
|
|
49
45
|
self._stopped = threading.Event()
|
|
46
|
+
self._paused_time = None
|
|
47
|
+
self._paused = threading.Event()
|
|
48
|
+
self._progress_log_interval = 5.0
|
|
49
|
+
self._last_progress_report_time = 0
|
|
50
50
|
self.progress = Progress(
|
|
51
51
|
message=self._stage,
|
|
52
52
|
total_cnt=1,
|
|
@@ -58,6 +58,8 @@ class InferenceRequest:
|
|
|
58
58
|
self._updated_at = self._created_at
|
|
59
59
|
self._finished = False
|
|
60
60
|
|
|
61
|
+
self.tracker = None
|
|
62
|
+
|
|
61
63
|
self.global_progress = None
|
|
62
64
|
self.global_progress_total = 1
|
|
63
65
|
self.global_progress_current = 0
|
|
@@ -95,10 +97,16 @@ class InferenceRequest:
|
|
|
95
97
|
def add_results(self, results: List[Dict]):
|
|
96
98
|
with self._lock:
|
|
97
99
|
self._pending_results.extend(results)
|
|
100
|
+
if self.pending_num() >= self.PENDING_RESULTS_MAX_SIZE:
|
|
101
|
+
logger.warning(
|
|
102
|
+
f"Pending results exceeded max size {self.PENDING_RESULTS_MAX_SIZE}, pausing inference request {self._uuid} for {self.PAUSE_SLEEP_MAX_WAIT} seconds."
|
|
103
|
+
)
|
|
104
|
+
self.pause()
|
|
98
105
|
self._updated()
|
|
99
106
|
|
|
100
107
|
def pop_pending_results(self, n: int = None):
|
|
101
108
|
with self._lock:
|
|
109
|
+
self.continue_if_paused()
|
|
102
110
|
if len(self._pending_results) == 0:
|
|
103
111
|
return []
|
|
104
112
|
if n is None:
|
|
@@ -135,9 +143,19 @@ class InferenceRequest:
|
|
|
135
143
|
)
|
|
136
144
|
self._updated()
|
|
137
145
|
|
|
146
|
+
def set_progress_log_interval(self, interval: float):
|
|
147
|
+
self._progress_log_interval = interval
|
|
148
|
+
|
|
138
149
|
def done(self, n=1):
|
|
139
150
|
with self._lock:
|
|
140
|
-
|
|
151
|
+
if (
|
|
152
|
+
self._progress_log_interval is None
|
|
153
|
+
or time.monotonic() - self._last_progress_report_time > self._progress_log_interval
|
|
154
|
+
) or (self.progress.current + n >= self.progress.total):
|
|
155
|
+
self.progress.iters_done_report(n)
|
|
156
|
+
self._last_progress_report_time = time.monotonic()
|
|
157
|
+
else:
|
|
158
|
+
self.progress.iters_done(n)
|
|
141
159
|
if self._stage == InferenceRequest.Stage.INFERENCE:
|
|
142
160
|
self.global_progress_current += n
|
|
143
161
|
if self.manager is not None:
|
|
@@ -164,6 +182,27 @@ class InferenceRequest:
|
|
|
164
182
|
def is_stopped(self):
|
|
165
183
|
return self._stopped.is_set()
|
|
166
184
|
|
|
185
|
+
def pause(self):
|
|
186
|
+
self._paused.set()
|
|
187
|
+
self._paused_time = time.monotonic()
|
|
188
|
+
self._updated()
|
|
189
|
+
|
|
190
|
+
def is_paused(self):
|
|
191
|
+
return self._paused.is_set()
|
|
192
|
+
|
|
193
|
+
def continue_if_paused(self):
|
|
194
|
+
if not self.is_paused():
|
|
195
|
+
return
|
|
196
|
+
logger.debug(f"Continuing paused inference request {self._uuid}")
|
|
197
|
+
self._paused.clear()
|
|
198
|
+
self._paused_time = None
|
|
199
|
+
self._updated()
|
|
200
|
+
|
|
201
|
+
def paused_for(self):
|
|
202
|
+
if not self.is_paused():
|
|
203
|
+
return 0
|
|
204
|
+
return time.monotonic() - self._paused_time
|
|
205
|
+
|
|
167
206
|
def is_finished(self):
|
|
168
207
|
return self._finished
|
|
169
208
|
|
|
@@ -200,6 +239,7 @@ class InferenceRequest:
|
|
|
200
239
|
"exception": self.exception_json(),
|
|
201
240
|
"is_inferring": self.is_inferring(),
|
|
202
241
|
"stopped": self.is_stopped(),
|
|
242
|
+
"paused": self.is_paused(),
|
|
203
243
|
"finished": self._finished,
|
|
204
244
|
"created_at": self._created_at,
|
|
205
245
|
"updated_at": self._updated_at,
|
|
@@ -353,6 +393,11 @@ class InferenceRequestsManager:
|
|
|
353
393
|
inference_request = self._inference_requests.get(inference_request_uuid)
|
|
354
394
|
if inference_request is None:
|
|
355
395
|
continue
|
|
396
|
+
if (
|
|
397
|
+
inference_request.is_paused()
|
|
398
|
+
and inference_request.paused_for() < InferenceRequest.PAUSE_SLEEP_MAX_WAIT
|
|
399
|
+
):
|
|
400
|
+
continue
|
|
356
401
|
if inference_request.is_expired():
|
|
357
402
|
self.remove(inference_request_uuid)
|
|
358
403
|
logger.debug(f"Expired inference request {inference_request_uuid} was deleted")
|
|
@@ -1,10 +1,50 @@
|
|
|
1
|
-
from typing import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
from typing import Any, Dict
|
|
2
|
+
|
|
3
|
+
import pandas as pd
|
|
4
|
+
|
|
5
|
+
from supervisely.app.widgets import (
|
|
6
|
+
Button,
|
|
7
|
+
Card,
|
|
8
|
+
ClassesTable,
|
|
9
|
+
Container,
|
|
10
|
+
FastTable,
|
|
11
|
+
Text,
|
|
12
|
+
)
|
|
13
|
+
from supervisely.geometry.any_geometry import AnyGeometry
|
|
14
|
+
from supervisely.geometry.bitmap import Bitmap
|
|
15
|
+
from supervisely.geometry.cuboid import Cuboid
|
|
16
|
+
from supervisely.geometry.cuboid_3d import Cuboid3d
|
|
17
|
+
from supervisely.geometry.geometry import Geometry
|
|
18
|
+
from supervisely.geometry.graph import GraphNodes
|
|
19
|
+
from supervisely.geometry.multichannel_bitmap import MultichannelBitmap
|
|
20
|
+
from supervisely.geometry.point import Point
|
|
21
|
+
from supervisely.geometry.point_3d import Point3d
|
|
22
|
+
from supervisely.geometry.pointcloud import Pointcloud
|
|
23
|
+
from supervisely.geometry.polygon import Polygon
|
|
24
|
+
from supervisely.geometry.polyline import Polyline
|
|
25
|
+
from supervisely.geometry.rectangle import Rectangle
|
|
26
|
+
from supervisely.geometry.oriented_bbox import OrientedBBox
|
|
27
|
+
from supervisely.project.project_meta import ProjectMeta
|
|
28
|
+
|
|
29
|
+
type_to_zmdi_icon = {
|
|
30
|
+
AnyGeometry: "zmdi zmdi-shape",
|
|
31
|
+
Rectangle: "zmdi zmdi-crop-din", # "zmdi zmdi-square-o"
|
|
32
|
+
# sly.Polygon: "icons8-polygon", # "zmdi zmdi-edit"
|
|
33
|
+
Polygon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAB6klEQVRYhe2Wuy8EURTGf+u5VESNXq2yhYZCoeBv8RcI1i6NVUpsoVCKkHjUGlFTiYb1mFmh2MiKjVXMudmb3cPOzB0VXzKZm5k53/nmvO6Ff4RHD5AD7gFP1l3Kd11AHvCBEpAVW2esAvWmK6t8l1O+W0lCQEnIJoAZxUnzNQNkZF36jrQjgoA+uaciCgc9VaExBOyh/6WWAi1VhbjOJ4FbIXkBtgkK0BNHnYqNKUIPeBPbKyDdzpld5T6wD9SE4AwYjfEDaXFeFzE/doUWuhqwiFsOCwqv2hV2lU/L+sHBscGTxdvSFVoXpAjCZdauMHVic6ndl6U1VBsJCFhTeNUU9IiIEo3qvQYGHAV0AyfC5wNLhKipXuBCjA5wT8WxcM1FMRoBymK44CjAE57hqIazwCfwQdARcXa3UXHuRXVucIjb7jYvNkdxBZg0TBFid7PQTRAtX2xOiXkuMAMqYwkIE848rZFbjyNAmw9bIeweaZ2A5TgC7PnwKkTPtN+cTOrsyN3FEWAjRTAX6sA5ek77gSL6+WHZVQDAIHAjhJtN78aAS3lXAXYIivBOnCdyOAUYB6o0xqsvziry7FLE/Cp20cNcJEjDr8MUmVOVRzkVN+Nd7vZGVXXgiwxtPiRS5WFhz4fEq/zv4AvToMn7vCn3eAAAAABJRU5ErkJggg==",
|
|
34
|
+
Bitmap: "zmdi zmdi-brush",
|
|
35
|
+
Polyline: "zmdi zmdi-gesture",
|
|
36
|
+
Point: "zmdi zmdi-dot-circle-alt",
|
|
37
|
+
Cuboid: "zmdi zmdi-ungroup", #
|
|
38
|
+
GraphNodes: "zmdi zmdi-grain",
|
|
39
|
+
Cuboid3d: "zmdi zmdi-codepen",
|
|
40
|
+
Pointcloud: "zmdi zmdi-cloud-outline", # "zmdi zmdi-border-clear"
|
|
41
|
+
MultichannelBitmap: "zmdi zmdi-layers", # "zmdi zmdi-collection-item"
|
|
42
|
+
Point3d: "zmdi zmdi-filter-center-focus", # "zmdi zmdi-select-all"
|
|
43
|
+
OrientedBBox: "zmdi zmdi-rotate-cw",
|
|
44
|
+
}
|
|
5
45
|
class ClassesSelector:
|
|
6
|
-
title = "Classes
|
|
7
|
-
description = "Select classes that will be used for inference"
|
|
46
|
+
title = "Classes"
|
|
47
|
+
description = "Select classes that will be used for inference. This classes are defined by the deployed model"
|
|
8
48
|
lock_message = "Select previous step to unlock"
|
|
9
49
|
|
|
10
50
|
def __init__(self):
|
|
@@ -24,7 +64,9 @@ class ClassesSelector:
|
|
|
24
64
|
# -------------------------------- #
|
|
25
65
|
|
|
26
66
|
# Classes
|
|
27
|
-
|
|
67
|
+
columns = ["class", "shape"]
|
|
68
|
+
self.classes_table = FastTable(columns=columns, page_size=100, is_selectable=True)
|
|
69
|
+
# self.classes_table = ClassesTable()
|
|
28
70
|
self.classes_table.hide()
|
|
29
71
|
# Add widgets to display ------------ #
|
|
30
72
|
self.display_widgets.extend([self.classes_table])
|
|
@@ -45,25 +87,36 @@ class ClassesSelector:
|
|
|
45
87
|
content=self.container,
|
|
46
88
|
lock_message=self.lock_message,
|
|
47
89
|
)
|
|
48
|
-
self.card.lock()
|
|
49
90
|
# -------------------------------- #
|
|
50
91
|
|
|
92
|
+
def lock(self):
|
|
93
|
+
self.card.lock()
|
|
94
|
+
self.classes_table.hide()
|
|
95
|
+
self.validator_text.hide()
|
|
96
|
+
|
|
97
|
+
def unlock(self):
|
|
98
|
+
self.card.unlock()
|
|
99
|
+
self.classes_table.show()
|
|
100
|
+
|
|
51
101
|
@property
|
|
52
102
|
def widgets_to_disable(self) -> list:
|
|
53
103
|
return [self.classes_table]
|
|
54
104
|
|
|
105
|
+
def set_project_meta(self, project_meta) -> None:
|
|
106
|
+
self._update_meta(project_meta)
|
|
107
|
+
|
|
55
108
|
def load_from_json(self, data: Dict[str, Any]) -> None:
|
|
56
109
|
if "classes" in data:
|
|
57
110
|
self.set_classes(data["classes"])
|
|
58
111
|
|
|
59
112
|
def get_selected_classes(self) -> list:
|
|
60
|
-
return self.classes_table.
|
|
113
|
+
return [row.row[0] for row in self.classes_table.get_selected_rows()]
|
|
61
114
|
|
|
62
115
|
def set_classes(self, classes) -> None:
|
|
63
|
-
self.classes_table.
|
|
116
|
+
self.classes_table.select_rows_by_value("class", classes)
|
|
64
117
|
|
|
65
118
|
def select_all_classes(self) -> None:
|
|
66
|
-
self.classes_table.
|
|
119
|
+
self.classes_table.select_rows(list(range(len(self.classes_table._rows_total))))
|
|
67
120
|
|
|
68
121
|
def get_settings(self) -> Dict[str, Any]:
|
|
69
122
|
return {"classes": self.get_selected_classes()}
|
|
@@ -73,7 +126,7 @@ class ClassesSelector:
|
|
|
73
126
|
return True
|
|
74
127
|
|
|
75
128
|
self.validator_text.hide()
|
|
76
|
-
selected_classes = self.
|
|
129
|
+
selected_classes = self.get_selected_classes()
|
|
77
130
|
n_classes = len(selected_classes)
|
|
78
131
|
|
|
79
132
|
if n_classes == 0:
|
|
@@ -89,3 +142,21 @@ class ClassesSelector:
|
|
|
89
142
|
self.validator_text.set(text=". ".join(message_parts), status=status)
|
|
90
143
|
self.validator_text.show()
|
|
91
144
|
return is_valid
|
|
145
|
+
|
|
146
|
+
def _update_meta(self, project_meta: ProjectMeta) -> None:
|
|
147
|
+
table_data = []
|
|
148
|
+
for obj_class in project_meta.obj_classes:
|
|
149
|
+
table_line = []
|
|
150
|
+
name = obj_class.name
|
|
151
|
+
icon = type_to_zmdi_icon[AnyGeometry]
|
|
152
|
+
icon = type_to_zmdi_icon.get(obj_class.geometry_type, icon)
|
|
153
|
+
shape = obj_class.geometry_type.geometry_name().lower()
|
|
154
|
+
if shape == "graph":
|
|
155
|
+
shape = "graph (keypoints)"
|
|
156
|
+
table_line = [name, shape]
|
|
157
|
+
table_data.append(table_line)
|
|
158
|
+
self._table_data = table_data
|
|
159
|
+
if self._table_data:
|
|
160
|
+
self.classes_table.read_pandas(pd.DataFrame(self._table_data))
|
|
161
|
+
else:
|
|
162
|
+
self.classes_table.clear()
|