supervisely 6.73.452__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 +25 -1
- supervisely/annotation/annotation.py +8 -2
- supervisely/annotation/json_geometries_map.py +13 -12
- supervisely/api/annotation_api.py +6 -3
- supervisely/api/api.py +2 -0
- supervisely/api/app_api.py +10 -1
- supervisely/api/dataset_api.py +74 -12
- supervisely/api/entities_collection_api.py +10 -0
- supervisely/api/entity_annotation/figure_api.py +28 -0
- 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 +4 -0
- supervisely/api/labeling_job_api.py +83 -1
- supervisely/api/labeling_queue_api.py +33 -7
- supervisely/api/module_api.py +5 -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/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/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/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 +22 -2
- 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/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 +795 -199
- supervisely/nn/inference/inference_request.py +42 -9
- 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 +113 -34
- supervisely/nn/inference/tracking/tracker_interface.py +7 -2
- 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/prediction_dto.py +12 -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/visualize.py +87 -90
- supervisely/nn/training/gui/classes_selector.py +16 -1
- supervisely/nn/training/train_app.py +28 -29
- 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 +40 -11
- 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.452.dist-info → supervisely-6.73.513.dist-info}/METADATA +56 -39
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/RECORD +189 -142
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/WHEEL +1 -1
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info/licenses}/LICENSE +0 -0
- {supervisely-6.73.452.dist-info → supervisely-6.73.513.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
from supervisely.project.versioning.schema_fields import VersionSchemaField
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class VideoSnapshotSchema:
|
|
12
|
+
schema_version: str
|
|
13
|
+
|
|
14
|
+
def datasets_schema(self, pa_module):
|
|
15
|
+
return pa_module.schema(
|
|
16
|
+
[
|
|
17
|
+
(VersionSchemaField.SRC_DATASET_ID, pa_module.int64()),
|
|
18
|
+
(VersionSchemaField.PARENT_SRC_DATASET_ID, pa_module.int64()),
|
|
19
|
+
(VersionSchemaField.NAME, pa_module.utf8()),
|
|
20
|
+
(VersionSchemaField.FULL_PATH, pa_module.utf8()),
|
|
21
|
+
(VersionSchemaField.DESCRIPTION, pa_module.utf8()),
|
|
22
|
+
(VersionSchemaField.CUSTOM_DATA, pa_module.utf8()),
|
|
23
|
+
]
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def videos_schema(self, pa_module):
|
|
27
|
+
return pa_module.schema(
|
|
28
|
+
[
|
|
29
|
+
(VersionSchemaField.SRC_VIDEO_ID, pa_module.int64()),
|
|
30
|
+
(VersionSchemaField.SRC_DATASET_ID, pa_module.int64()),
|
|
31
|
+
(VersionSchemaField.NAME, pa_module.utf8()),
|
|
32
|
+
(VersionSchemaField.HASH, pa_module.utf8()),
|
|
33
|
+
(VersionSchemaField.LINK, pa_module.utf8()),
|
|
34
|
+
(VersionSchemaField.FRAMES_COUNT, pa_module.int32()),
|
|
35
|
+
(VersionSchemaField.FRAME_WIDTH, pa_module.int32()),
|
|
36
|
+
(VersionSchemaField.FRAME_HEIGHT, pa_module.int32()),
|
|
37
|
+
(VersionSchemaField.FRAMES_TO_TIMECODES, pa_module.utf8()),
|
|
38
|
+
(VersionSchemaField.META, pa_module.utf8()),
|
|
39
|
+
(VersionSchemaField.CUSTOM_DATA, pa_module.utf8()),
|
|
40
|
+
(VersionSchemaField.CREATED_AT, pa_module.utf8()),
|
|
41
|
+
(VersionSchemaField.UPDATED_AT, pa_module.utf8()),
|
|
42
|
+
(VersionSchemaField.ANN_JSON, pa_module.utf8()),
|
|
43
|
+
]
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def objects_schema(self, pa_module):
|
|
47
|
+
return pa_module.schema(
|
|
48
|
+
[
|
|
49
|
+
(VersionSchemaField.SRC_OBJECT_ID, pa_module.int64()),
|
|
50
|
+
(VersionSchemaField.SRC_VIDEO_ID, pa_module.int64()),
|
|
51
|
+
(VersionSchemaField.CLASS_NAME, pa_module.utf8()),
|
|
52
|
+
(VersionSchemaField.KEY, pa_module.utf8()),
|
|
53
|
+
(VersionSchemaField.TAGS_JSON, pa_module.utf8()),
|
|
54
|
+
]
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def figures_schema(self, pa_module):
|
|
58
|
+
return pa_module.schema(
|
|
59
|
+
[
|
|
60
|
+
(VersionSchemaField.SRC_FIGURE_ID, pa_module.int64()),
|
|
61
|
+
(VersionSchemaField.SRC_OBJECT_ID, pa_module.int64()),
|
|
62
|
+
(VersionSchemaField.SRC_VIDEO_ID, pa_module.int64()),
|
|
63
|
+
(VersionSchemaField.FRAME_INDEX, pa_module.int32()),
|
|
64
|
+
(VersionSchemaField.GEOMETRY_TYPE, pa_module.utf8()),
|
|
65
|
+
(VersionSchemaField.GEOMETRY_JSON, pa_module.utf8()),
|
|
66
|
+
]
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def dataset_row(
|
|
70
|
+
self,
|
|
71
|
+
*,
|
|
72
|
+
src_dataset_id: int,
|
|
73
|
+
parent_src_dataset_id: Optional[int],
|
|
74
|
+
name: str,
|
|
75
|
+
full_path: str,
|
|
76
|
+
description: Optional[str],
|
|
77
|
+
custom_data: Optional[dict],
|
|
78
|
+
) -> Dict[str, Any]:
|
|
79
|
+
return {
|
|
80
|
+
VersionSchemaField.SRC_DATASET_ID: src_dataset_id,
|
|
81
|
+
VersionSchemaField.PARENT_SRC_DATASET_ID: parent_src_dataset_id,
|
|
82
|
+
VersionSchemaField.NAME: name,
|
|
83
|
+
VersionSchemaField.FULL_PATH: full_path,
|
|
84
|
+
VersionSchemaField.DESCRIPTION: description,
|
|
85
|
+
VersionSchemaField.CUSTOM_DATA: (
|
|
86
|
+
json.dumps(custom_data) if isinstance(custom_data, dict) and len(custom_data) > 0 else None
|
|
87
|
+
),
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def video_row(
|
|
91
|
+
self,
|
|
92
|
+
*,
|
|
93
|
+
src_video_id: int,
|
|
94
|
+
src_dataset_id: int,
|
|
95
|
+
name: str,
|
|
96
|
+
hash: Optional[str],
|
|
97
|
+
link: Optional[str],
|
|
98
|
+
frames_count: Optional[int],
|
|
99
|
+
frame_width: Optional[int],
|
|
100
|
+
frame_height: Optional[int],
|
|
101
|
+
frames_to_timecodes: Optional[list],
|
|
102
|
+
meta: Optional[dict],
|
|
103
|
+
custom_data: Optional[dict],
|
|
104
|
+
created_at: Optional[str],
|
|
105
|
+
updated_at: Optional[str],
|
|
106
|
+
ann_json: dict,
|
|
107
|
+
) -> Dict[str, Any]:
|
|
108
|
+
return {
|
|
109
|
+
VersionSchemaField.SRC_VIDEO_ID: src_video_id,
|
|
110
|
+
VersionSchemaField.SRC_DATASET_ID: src_dataset_id,
|
|
111
|
+
VersionSchemaField.NAME: name,
|
|
112
|
+
VersionSchemaField.HASH: hash,
|
|
113
|
+
VersionSchemaField.LINK: link,
|
|
114
|
+
VersionSchemaField.FRAMES_COUNT: frames_count,
|
|
115
|
+
VersionSchemaField.FRAME_WIDTH: frame_width,
|
|
116
|
+
VersionSchemaField.FRAME_HEIGHT: frame_height,
|
|
117
|
+
VersionSchemaField.FRAMES_TO_TIMECODES: (
|
|
118
|
+
json.dumps(frames_to_timecodes) if frames_to_timecodes else None
|
|
119
|
+
),
|
|
120
|
+
VersionSchemaField.META: json.dumps(meta) if meta else None,
|
|
121
|
+
VersionSchemaField.CUSTOM_DATA: json.dumps(custom_data) if custom_data else None,
|
|
122
|
+
VersionSchemaField.CREATED_AT: created_at,
|
|
123
|
+
VersionSchemaField.UPDATED_AT: updated_at,
|
|
124
|
+
VersionSchemaField.ANN_JSON: json.dumps(ann_json),
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
def object_row(
|
|
128
|
+
self,
|
|
129
|
+
*,
|
|
130
|
+
src_object_id: int,
|
|
131
|
+
src_video_id: int,
|
|
132
|
+
class_name: str,
|
|
133
|
+
key_hex: str,
|
|
134
|
+
tags_json: Optional[List[Dict[str, Any]]],
|
|
135
|
+
) -> Dict[str, Any]:
|
|
136
|
+
return {
|
|
137
|
+
VersionSchemaField.SRC_OBJECT_ID: src_object_id,
|
|
138
|
+
VersionSchemaField.SRC_VIDEO_ID: src_video_id,
|
|
139
|
+
VersionSchemaField.CLASS_NAME: class_name,
|
|
140
|
+
VersionSchemaField.KEY: key_hex,
|
|
141
|
+
VersionSchemaField.TAGS_JSON: json.dumps(tags_json) if tags_json is not None else None,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
def figure_row(
|
|
145
|
+
self,
|
|
146
|
+
*,
|
|
147
|
+
src_figure_id: int,
|
|
148
|
+
src_object_id: int,
|
|
149
|
+
src_video_id: int,
|
|
150
|
+
frame_index: int,
|
|
151
|
+
geometry_type: str,
|
|
152
|
+
geometry_json: dict,
|
|
153
|
+
) -> Dict[str, Any]:
|
|
154
|
+
return {
|
|
155
|
+
VersionSchemaField.SRC_FIGURE_ID: src_figure_id,
|
|
156
|
+
VersionSchemaField.SRC_OBJECT_ID: src_object_id,
|
|
157
|
+
VersionSchemaField.SRC_VIDEO_ID: src_video_id,
|
|
158
|
+
VersionSchemaField.FRAME_INDEX: frame_index,
|
|
159
|
+
VersionSchemaField.GEOMETRY_TYPE: geometry_type,
|
|
160
|
+
VersionSchemaField.GEOMETRY_JSON: json.dumps(geometry_json),
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
def dataset_row_from_ds_info(self, ds_info, *, full_path: str, custom_data: Optional[dict]):
|
|
164
|
+
return self.dataset_row(
|
|
165
|
+
src_dataset_id=ds_info.id,
|
|
166
|
+
parent_src_dataset_id=ds_info.parent_id,
|
|
167
|
+
name=ds_info.name,
|
|
168
|
+
full_path=full_path,
|
|
169
|
+
description=getattr(ds_info, "description", None),
|
|
170
|
+
custom_data=custom_data,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
def video_row_from_video_info(self, video_info, *, src_dataset_id: int, ann_json: dict):
|
|
174
|
+
return self.video_row(
|
|
175
|
+
src_video_id=video_info.id,
|
|
176
|
+
src_dataset_id=src_dataset_id,
|
|
177
|
+
name=video_info.name,
|
|
178
|
+
hash=getattr(video_info, "hash", None),
|
|
179
|
+
link=getattr(video_info, "link", None),
|
|
180
|
+
frames_count=getattr(video_info, "frames_count", None),
|
|
181
|
+
frame_width=getattr(video_info, "frame_width", None),
|
|
182
|
+
frame_height=getattr(video_info, "frame_height", None),
|
|
183
|
+
frames_to_timecodes=getattr(video_info, "frames_to_timecodes", None),
|
|
184
|
+
meta=getattr(video_info, "meta", None),
|
|
185
|
+
custom_data=getattr(video_info, "custom_data", None),
|
|
186
|
+
created_at=getattr(video_info, "created_at", None),
|
|
187
|
+
updated_at=getattr(video_info, "updated_at", None),
|
|
188
|
+
ann_json=ann_json,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
def object_row_from_object(self, obj, *, src_object_id: int, src_video_id: int) -> Dict[str, Any]:
|
|
192
|
+
return self.object_row(
|
|
193
|
+
src_object_id=src_object_id,
|
|
194
|
+
src_video_id=src_video_id,
|
|
195
|
+
class_name=obj.obj_class.name,
|
|
196
|
+
key_hex=obj.key().hex,
|
|
197
|
+
tags_json=obj.tags.to_json() if getattr(obj, "tags", None) is not None else None,
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
def figure_row_from_figure(
|
|
201
|
+
self,
|
|
202
|
+
fig,
|
|
203
|
+
*,
|
|
204
|
+
figure_row_idx: int,
|
|
205
|
+
src_object_id: int,
|
|
206
|
+
src_video_id: int,
|
|
207
|
+
frame_index: int,
|
|
208
|
+
) -> Dict[str, Any]:
|
|
209
|
+
return self.figure_row(
|
|
210
|
+
src_figure_id=figure_row_idx + 1,
|
|
211
|
+
src_object_id=src_object_id,
|
|
212
|
+
src_video_id=src_video_id,
|
|
213
|
+
frame_index=frame_index,
|
|
214
|
+
geometry_type=fig.geometry.geometry_name(),
|
|
215
|
+
geometry_json=fig.geometry.to_json(),
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
_VIDEO_SCHEMAS: Dict[str, VideoSnapshotSchema] = {
|
|
219
|
+
"v2.0.0": VideoSnapshotSchema(schema_version="v2.0.0"),
|
|
220
|
+
}
|
|
221
|
+
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import Any, Dict
|
|
6
|
+
|
|
7
|
+
from supervisely.api.api import Api
|
|
8
|
+
from supervisely.api.module_api import ApiField
|
|
9
|
+
from supervisely.geometry.mask_3d import Mask3D
|
|
10
|
+
from supervisely.project.data_version import VersionSchemaField
|
|
11
|
+
from supervisely.project.project_meta import ProjectMeta
|
|
12
|
+
from supervisely.project.versioning.schema_fields import VersionSchemaField
|
|
13
|
+
from supervisely.video_annotation.key_id_map import KeyIdMap
|
|
14
|
+
from supervisely.volume_annotation.volume_annotation import VolumeAnnotation
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class VolumeSnapshotSchema:
|
|
19
|
+
schema_version: str
|
|
20
|
+
|
|
21
|
+
def datasets_table_schema(self, pa_module):
|
|
22
|
+
return pa_module.schema(
|
|
23
|
+
[
|
|
24
|
+
(VersionSchemaField.SRC_DATASET_ID, pa_module.int64()),
|
|
25
|
+
(VersionSchemaField.JSON, pa_module.large_string()),
|
|
26
|
+
]
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
def volumes_table_schema(self, pa_module):
|
|
30
|
+
return pa_module.schema(
|
|
31
|
+
[
|
|
32
|
+
(VersionSchemaField.SRC_VOLUME_ID, pa_module.int64()),
|
|
33
|
+
(VersionSchemaField.SRC_DATASET_ID, pa_module.int64()),
|
|
34
|
+
(VersionSchemaField.JSON, pa_module.large_string()),
|
|
35
|
+
]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
def annotations_table_schema(self, pa_module):
|
|
39
|
+
return pa_module.schema(
|
|
40
|
+
[
|
|
41
|
+
(VersionSchemaField.SRC_VOLUME_ID, pa_module.int64()),
|
|
42
|
+
(VersionSchemaField.ANNOTATION, pa_module.large_string()),
|
|
43
|
+
]
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def dataset_row_from_record(self, dataset_record: dict) -> Dict[str, Any]:
|
|
47
|
+
return {
|
|
48
|
+
VersionSchemaField.SRC_DATASET_ID: dataset_record.get(ApiField.ID),
|
|
49
|
+
VersionSchemaField.JSON: json.dumps(dataset_record, ensure_ascii=False),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
def volume_row_from_record(self, volume_record: dict) -> Dict[str, Any]:
|
|
53
|
+
return {
|
|
54
|
+
VersionSchemaField.SRC_VOLUME_ID: volume_record.get(ApiField.ID),
|
|
55
|
+
VersionSchemaField.SRC_DATASET_ID: volume_record.get(ApiField.DATASET_ID),
|
|
56
|
+
VersionSchemaField.JSON: json.dumps(volume_record, ensure_ascii=False),
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
def annotation_row_from_dict(self, *, src_volume_id: int, annotation: dict) -> Dict[str, Any]:
|
|
60
|
+
return {
|
|
61
|
+
VersionSchemaField.SRC_VOLUME_ID: src_volume_id,
|
|
62
|
+
VersionSchemaField.ANNOTATION: json.dumps(annotation, ensure_ascii=False),
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
def annotation_dict_from_raw(
|
|
66
|
+
self,
|
|
67
|
+
*,
|
|
68
|
+
api: Api,
|
|
69
|
+
raw_ann_json: dict,
|
|
70
|
+
project_meta_obj: ProjectMeta,
|
|
71
|
+
key_id_map: KeyIdMap,
|
|
72
|
+
) -> dict:
|
|
73
|
+
ann = VolumeAnnotation.from_json(raw_ann_json, project_meta_obj, key_id_map)
|
|
74
|
+
self._load_mask_geometries(api, ann, key_id_map)
|
|
75
|
+
return ann.to_json()
|
|
76
|
+
|
|
77
|
+
@staticmethod
|
|
78
|
+
def _load_mask_geometries(api: Api, ann: VolumeAnnotation, key_id_map: KeyIdMap) -> None:
|
|
79
|
+
for sf in ann.spatial_figures:
|
|
80
|
+
if sf.geometry.name() != Mask3D.name():
|
|
81
|
+
continue
|
|
82
|
+
api.volume.figure.load_sf_geometry(sf, key_id_map)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
_VOLUME_SCHEMAS: Dict[str, VolumeSnapshotSchema] = {
|
|
86
|
+
"v2.0.0": VolumeSnapshotSchema(schema_version="v2.0.0"),
|
|
87
|
+
}
|