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.
Files changed (203) hide show
  1. supervisely/__init__.py +137 -1
  2. supervisely/_utils.py +81 -0
  3. supervisely/annotation/annotation.py +8 -2
  4. supervisely/annotation/json_geometries_map.py +14 -11
  5. supervisely/annotation/label.py +80 -3
  6. supervisely/api/annotation_api.py +14 -11
  7. supervisely/api/api.py +59 -38
  8. supervisely/api/app_api.py +11 -2
  9. supervisely/api/dataset_api.py +74 -12
  10. supervisely/api/entities_collection_api.py +10 -0
  11. supervisely/api/entity_annotation/figure_api.py +52 -4
  12. supervisely/api/entity_annotation/object_api.py +3 -3
  13. supervisely/api/entity_annotation/tag_api.py +63 -12
  14. supervisely/api/guides_api.py +210 -0
  15. supervisely/api/image_api.py +72 -1
  16. supervisely/api/labeling_job_api.py +83 -1
  17. supervisely/api/labeling_queue_api.py +33 -7
  18. supervisely/api/module_api.py +9 -0
  19. supervisely/api/project_api.py +71 -26
  20. supervisely/api/storage_api.py +3 -1
  21. supervisely/api/task_api.py +13 -2
  22. supervisely/api/team_api.py +4 -3
  23. supervisely/api/video/video_annotation_api.py +119 -3
  24. supervisely/api/video/video_api.py +65 -14
  25. supervisely/api/video/video_figure_api.py +24 -11
  26. supervisely/app/__init__.py +1 -1
  27. supervisely/app/content.py +23 -7
  28. supervisely/app/development/development.py +18 -2
  29. supervisely/app/fastapi/__init__.py +1 -0
  30. supervisely/app/fastapi/custom_static_files.py +1 -1
  31. supervisely/app/fastapi/multi_user.py +105 -0
  32. supervisely/app/fastapi/subapp.py +88 -42
  33. supervisely/app/fastapi/websocket.py +77 -9
  34. supervisely/app/singleton.py +21 -0
  35. supervisely/app/v1/app_service.py +18 -2
  36. supervisely/app/v1/constants.py +7 -1
  37. supervisely/app/widgets/__init__.py +6 -0
  38. supervisely/app/widgets/activity_feed/__init__.py +0 -0
  39. supervisely/app/widgets/activity_feed/activity_feed.py +239 -0
  40. supervisely/app/widgets/activity_feed/style.css +78 -0
  41. supervisely/app/widgets/activity_feed/template.html +22 -0
  42. supervisely/app/widgets/card/card.py +20 -0
  43. supervisely/app/widgets/classes_list_selector/classes_list_selector.py +121 -9
  44. supervisely/app/widgets/classes_list_selector/template.html +60 -93
  45. supervisely/app/widgets/classes_mapping/classes_mapping.py +13 -12
  46. supervisely/app/widgets/classes_table/classes_table.py +1 -0
  47. supervisely/app/widgets/deploy_model/deploy_model.py +56 -35
  48. supervisely/app/widgets/dialog/dialog.py +12 -0
  49. supervisely/app/widgets/dialog/template.html +2 -1
  50. supervisely/app/widgets/ecosystem_model_selector/ecosystem_model_selector.py +1 -1
  51. supervisely/app/widgets/experiment_selector/experiment_selector.py +8 -0
  52. supervisely/app/widgets/fast_table/fast_table.py +184 -60
  53. supervisely/app/widgets/fast_table/template.html +1 -1
  54. supervisely/app/widgets/heatmap/__init__.py +0 -0
  55. supervisely/app/widgets/heatmap/heatmap.py +564 -0
  56. supervisely/app/widgets/heatmap/script.js +533 -0
  57. supervisely/app/widgets/heatmap/style.css +233 -0
  58. supervisely/app/widgets/heatmap/template.html +21 -0
  59. supervisely/app/widgets/modal/__init__.py +0 -0
  60. supervisely/app/widgets/modal/modal.py +198 -0
  61. supervisely/app/widgets/modal/template.html +10 -0
  62. supervisely/app/widgets/object_class_view/object_class_view.py +3 -0
  63. supervisely/app/widgets/radio_tabs/radio_tabs.py +18 -2
  64. supervisely/app/widgets/radio_tabs/template.html +1 -0
  65. supervisely/app/widgets/select/select.py +6 -3
  66. supervisely/app/widgets/select_class/__init__.py +0 -0
  67. supervisely/app/widgets/select_class/select_class.py +363 -0
  68. supervisely/app/widgets/select_class/template.html +50 -0
  69. supervisely/app/widgets/select_cuda/select_cuda.py +22 -0
  70. supervisely/app/widgets/select_dataset_tree/select_dataset_tree.py +65 -7
  71. supervisely/app/widgets/select_tag/__init__.py +0 -0
  72. supervisely/app/widgets/select_tag/select_tag.py +352 -0
  73. supervisely/app/widgets/select_tag/template.html +64 -0
  74. supervisely/app/widgets/select_team/select_team.py +37 -4
  75. supervisely/app/widgets/select_team/template.html +4 -5
  76. supervisely/app/widgets/select_user/__init__.py +0 -0
  77. supervisely/app/widgets/select_user/select_user.py +270 -0
  78. supervisely/app/widgets/select_user/template.html +13 -0
  79. supervisely/app/widgets/select_workspace/select_workspace.py +59 -10
  80. supervisely/app/widgets/select_workspace/template.html +9 -12
  81. supervisely/app/widgets/table/table.py +68 -13
  82. supervisely/app/widgets/tree_select/tree_select.py +2 -0
  83. supervisely/aug/aug.py +6 -2
  84. supervisely/convert/base_converter.py +1 -0
  85. supervisely/convert/converter.py +2 -2
  86. supervisely/convert/image/csv/csv_converter.py +24 -15
  87. supervisely/convert/image/image_converter.py +3 -1
  88. supervisely/convert/image/image_helper.py +48 -4
  89. supervisely/convert/image/label_studio/label_studio_converter.py +2 -0
  90. supervisely/convert/image/medical2d/medical2d_helper.py +2 -24
  91. supervisely/convert/image/multispectral/multispectral_converter.py +6 -0
  92. supervisely/convert/image/pascal_voc/pascal_voc_converter.py +8 -5
  93. supervisely/convert/image/pascal_voc/pascal_voc_helper.py +7 -0
  94. supervisely/convert/pointcloud/kitti_3d/kitti_3d_converter.py +33 -3
  95. supervisely/convert/pointcloud/kitti_3d/kitti_3d_helper.py +12 -5
  96. supervisely/convert/pointcloud/las/las_converter.py +13 -1
  97. supervisely/convert/pointcloud/las/las_helper.py +110 -11
  98. supervisely/convert/pointcloud/nuscenes_conv/nuscenes_converter.py +27 -16
  99. supervisely/convert/pointcloud/pointcloud_converter.py +91 -3
  100. supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_converter.py +58 -22
  101. supervisely/convert/pointcloud_episodes/nuscenes_conv/nuscenes_helper.py +21 -47
  102. supervisely/convert/video/__init__.py +1 -0
  103. supervisely/convert/video/multi_view/__init__.py +0 -0
  104. supervisely/convert/video/multi_view/multi_view.py +543 -0
  105. supervisely/convert/video/sly/sly_video_converter.py +359 -3
  106. supervisely/convert/video/video_converter.py +24 -4
  107. supervisely/convert/volume/dicom/dicom_converter.py +13 -5
  108. supervisely/convert/volume/dicom/dicom_helper.py +30 -18
  109. supervisely/geometry/constants.py +1 -0
  110. supervisely/geometry/geometry.py +4 -0
  111. supervisely/geometry/helpers.py +5 -1
  112. supervisely/geometry/oriented_bbox.py +676 -0
  113. supervisely/geometry/polyline_3d.py +110 -0
  114. supervisely/geometry/rectangle.py +2 -1
  115. supervisely/io/env.py +76 -1
  116. supervisely/io/fs.py +21 -0
  117. supervisely/nn/benchmark/base_evaluator.py +104 -11
  118. supervisely/nn/benchmark/instance_segmentation/evaluator.py +1 -8
  119. supervisely/nn/benchmark/object_detection/evaluator.py +20 -4
  120. supervisely/nn/benchmark/object_detection/vis_metrics/pr_curve.py +10 -5
  121. supervisely/nn/benchmark/semantic_segmentation/evaluator.py +34 -16
  122. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/confusion_matrix.py +1 -1
  123. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/frequently_confused.py +1 -1
  124. supervisely/nn/benchmark/semantic_segmentation/vis_metrics/overview.py +1 -1
  125. supervisely/nn/benchmark/visualization/evaluation_result.py +66 -4
  126. supervisely/nn/inference/cache.py +43 -18
  127. supervisely/nn/inference/gui/serving_gui_template.py +5 -2
  128. supervisely/nn/inference/inference.py +916 -222
  129. supervisely/nn/inference/inference_request.py +55 -10
  130. supervisely/nn/inference/predict_app/gui/classes_selector.py +83 -12
  131. supervisely/nn/inference/predict_app/gui/gui.py +676 -488
  132. supervisely/nn/inference/predict_app/gui/input_selector.py +205 -26
  133. supervisely/nn/inference/predict_app/gui/model_selector.py +2 -4
  134. supervisely/nn/inference/predict_app/gui/output_selector.py +46 -6
  135. supervisely/nn/inference/predict_app/gui/settings_selector.py +756 -59
  136. supervisely/nn/inference/predict_app/gui/tags_selector.py +1 -1
  137. supervisely/nn/inference/predict_app/gui/utils.py +236 -119
  138. supervisely/nn/inference/predict_app/predict_app.py +2 -2
  139. supervisely/nn/inference/session.py +43 -35
  140. supervisely/nn/inference/tracking/bbox_tracking.py +118 -35
  141. supervisely/nn/inference/tracking/point_tracking.py +5 -1
  142. supervisely/nn/inference/tracking/tracker_interface.py +10 -1
  143. supervisely/nn/inference/uploader.py +139 -12
  144. supervisely/nn/live_training/__init__.py +7 -0
  145. supervisely/nn/live_training/api_server.py +111 -0
  146. supervisely/nn/live_training/artifacts_utils.py +243 -0
  147. supervisely/nn/live_training/checkpoint_utils.py +229 -0
  148. supervisely/nn/live_training/dynamic_sampler.py +44 -0
  149. supervisely/nn/live_training/helpers.py +14 -0
  150. supervisely/nn/live_training/incremental_dataset.py +146 -0
  151. supervisely/nn/live_training/live_training.py +497 -0
  152. supervisely/nn/live_training/loss_plateau_detector.py +111 -0
  153. supervisely/nn/live_training/request_queue.py +52 -0
  154. supervisely/nn/model/model_api.py +9 -0
  155. supervisely/nn/model/prediction.py +2 -1
  156. supervisely/nn/model/prediction_session.py +26 -14
  157. supervisely/nn/prediction_dto.py +19 -1
  158. supervisely/nn/tracker/base_tracker.py +11 -1
  159. supervisely/nn/tracker/botsort/botsort_config.yaml +0 -1
  160. supervisely/nn/tracker/botsort/tracker/mc_bot_sort.py +7 -4
  161. supervisely/nn/tracker/botsort_tracker.py +94 -65
  162. supervisely/nn/tracker/utils.py +4 -5
  163. supervisely/nn/tracker/visualize.py +93 -93
  164. supervisely/nn/training/gui/classes_selector.py +16 -1
  165. supervisely/nn/training/gui/train_val_splits_selector.py +52 -31
  166. supervisely/nn/training/train_app.py +46 -31
  167. supervisely/project/data_version.py +115 -51
  168. supervisely/project/download.py +1 -1
  169. supervisely/project/pointcloud_episode_project.py +37 -8
  170. supervisely/project/pointcloud_project.py +30 -2
  171. supervisely/project/project.py +14 -2
  172. supervisely/project/project_meta.py +27 -1
  173. supervisely/project/project_settings.py +32 -18
  174. supervisely/project/versioning/__init__.py +1 -0
  175. supervisely/project/versioning/common.py +20 -0
  176. supervisely/project/versioning/schema_fields.py +35 -0
  177. supervisely/project/versioning/video_schema.py +221 -0
  178. supervisely/project/versioning/volume_schema.py +87 -0
  179. supervisely/project/video_project.py +717 -15
  180. supervisely/project/volume_project.py +623 -5
  181. supervisely/template/experiment/experiment.html.jinja +4 -4
  182. supervisely/template/experiment/experiment_generator.py +14 -21
  183. supervisely/template/live_training/__init__.py +0 -0
  184. supervisely/template/live_training/header.html.jinja +96 -0
  185. supervisely/template/live_training/live_training.html.jinja +51 -0
  186. supervisely/template/live_training/live_training_generator.py +464 -0
  187. supervisely/template/live_training/sly-style.css +402 -0
  188. supervisely/template/live_training/template.html.jinja +18 -0
  189. supervisely/versions.json +28 -26
  190. supervisely/video/sampling.py +39 -20
  191. supervisely/video/video.py +41 -12
  192. supervisely/video_annotation/video_figure.py +38 -4
  193. supervisely/video_annotation/video_object.py +29 -4
  194. supervisely/volume/stl_converter.py +2 -0
  195. supervisely/worker_api/agent_rpc.py +24 -1
  196. supervisely/worker_api/rpc_servicer.py +31 -7
  197. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/METADATA +58 -40
  198. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/RECORD +203 -155
  199. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/WHEEL +1 -1
  200. supervisely_lib/__init__.py +6 -1
  201. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/entry_points.txt +0 -0
  202. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info/licenses}/LICENSE +0 -0
  203. {supervisely-6.73.438.dist-info → supervisely-6.73.513.dist-info}/top_level.txt +0 -0
@@ -10,6 +10,7 @@ from supervisely._utils import take_with_default
10
10
  from supervisely.annotation.tag_meta import TagValueType
11
11
  from supervisely.collection.str_enum import StrEnum
12
12
  from supervisely.io.json import JsonSerializable
13
+ from supervisely.project.project_type import ProjectType
13
14
  from supervisely.sly_logger import logger
14
15
 
15
16
 
@@ -184,31 +185,44 @@ class ProjectSettings(JsonSerializable):
184
185
 
185
186
  def validate(self, meta):
186
187
  if meta.project_settings.multiview_enabled is True:
187
- mtag_name = meta.project_settings.multiview_tag_name
188
- if mtag_name is None:
189
- if meta.project_settings.multiview_tag_id is None:
190
- return # (tag_name, tag_id) == (None, None) is OK
191
- mtag_name = meta.get_tag_name_by_id(meta.project_settings.multiview_tag_id)
188
+ # Images multiview
189
+ if meta.project_type == ProjectType.IMAGES:
190
+ mtag_name = meta.project_settings.multiview_tag_name
192
191
  if mtag_name is None:
192
+ if meta.project_settings.multiview_tag_id is None:
193
+ return # (tag_name, tag_id) == (None, None) is OK
194
+ mtag_name = meta.get_tag_name_by_id(meta.project_settings.multiview_tag_id)
195
+ if mtag_name is None:
196
+ raise RuntimeError(
197
+ f"The multi-view tag with ID={meta.project_settings.multiview_tag_id} was not found in the project meta. "
198
+ "Please directly add the tag meta that will be used for image grouping for multi-view labeling interface."
199
+ )
200
+
201
+ multi_tag = meta.get_tag_meta(mtag_name)
202
+ if multi_tag is None:
193
203
  raise RuntimeError(
194
- f"The multi-view tag with ID={meta.project_settings.multiview_tag_id} was not found in the project meta. "
195
- "Please directly add the tag meta that will be used for image grouping for multi-view labeling interface."
204
+ f"The multi-view tag '{mtag_name}' was not found in the project meta. Please directly add the tag meta "
205
+ "that will be used for image grouping for multi-view labeling interface."
206
+ )
207
+ elif multi_tag.value_type != TagValueType.ANY_STRING:
208
+ raise RuntimeError(
209
+ f"The multi-view tag value type should be '{TagValueType.ANY_STRING}'. The provided type: '{multi_tag.value_type}'."
196
210
  )
197
211
 
198
- multi_tag = meta.get_tag_meta(mtag_name)
199
- if multi_tag is None:
200
- raise RuntimeError(
201
- f"The multi-view tag '{mtag_name}' was not found in the project meta. Please directly add the tag meta "
202
- "that will be used for image grouping for multi-view labeling interface."
203
- )
204
- elif multi_tag.value_type != TagValueType.ANY_STRING:
205
- raise RuntimeError(
206
- f"The multi-view tag value type should be '{TagValueType.ANY_STRING}'. The provided type: '{multi_tag.value_type}'."
207
- )
212
+ # Video multiview
213
+ elif meta.project_type == ProjectType.VIDEOS:
214
+ if (
215
+ meta.project_settings.multiview_tag_name is not None
216
+ or meta.project_settings.multiview_tag_id is not None
217
+ ):
218
+ raise RuntimeError(
219
+ "For video projects, multiview_tag_name and multiview_tag_id should be None. "
220
+ "Videos are grouped by datasets, not by tags."
221
+ )
208
222
 
209
223
  if meta.project_settings.labeling_interface is not None:
210
224
  if meta.project_settings.labeling_interface not in LabelingInterface.values():
211
225
  raise RuntimeError(
212
226
  f"Invalid labeling interface value: {meta.project_settings.labeling_interface}. "
213
227
  f"The available values: {LabelingInterface.values()}"
214
- )
228
+ )
@@ -0,0 +1 @@
1
+ from supervisely.project.versioning.schema_fields import VersionSchemaField
@@ -0,0 +1,20 @@
1
+ from supervisely.project.versioning.video_schema import VideoSnapshotSchema, _VIDEO_SCHEMAS
2
+ from supervisely.project.versioning.volume_schema import VolumeSnapshotSchema, _VOLUME_SCHEMAS
3
+
4
+ DEFAULT_IMAGE_SCHEMA_VERSION = "v1.0.0"
5
+ DEFAULT_VOLUME_SCHEMA_VERSION = "v2.0.0"
6
+ DEFAULT_VIDEO_SCHEMA_VERSION = "v2.0.0"
7
+
8
+
9
+ def get_video_snapshot_schema(schema_version: str) -> VideoSnapshotSchema:
10
+ schema = _VIDEO_SCHEMAS.get(schema_version)
11
+ if schema is None:
12
+ raise RuntimeError(f"Unsupported video snapshot schema_version: {schema_version!r}")
13
+ return schema
14
+
15
+
16
+ def get_volume_snapshot_schema(schema_version: str) -> VolumeSnapshotSchema:
17
+ schema = _VOLUME_SCHEMAS.get(schema_version)
18
+ if schema is None:
19
+ raise RuntimeError(f"Unsupported volume snapshot schema_version: {schema_version!r}")
20
+ return schema
@@ -0,0 +1,35 @@
1
+ class VersionSchemaField:
2
+ """String constants used as column names across snapshot table schemas."""
3
+
4
+ SCHEMA_VERSION = "schema_version"
5
+ TABLES = "tables"
6
+ NAME = "name"
7
+ PATH = "path"
8
+ ROW_COUNT = "row_count"
9
+ SRC_DATASET_ID = "src_dataset_id"
10
+ PARENT_SRC_DATASET_ID = "parent_src_dataset_id"
11
+ FULL_PATH = "full_path"
12
+ DESCRIPTION = "description"
13
+ SRC_VIDEO_ID = "src_video_id"
14
+ SRC_VOLUME_ID = "src_volume_id"
15
+ HASH = "hash"
16
+ LINK = "link"
17
+ FRAMES_COUNT = "frames_count"
18
+ FRAME_WIDTH = "frame_width"
19
+ FRAME_HEIGHT = "frame_height"
20
+ FRAMES_TO_TIMECODES = "frames_to_timecodes"
21
+ META = "meta"
22
+ CUSTOM_DATA = "custom_data"
23
+ CREATED_AT = "created_at"
24
+ UPDATED_AT = "updated_at"
25
+ ANN_JSON = "ann_json"
26
+ JSON = "json"
27
+ ANNOTATION = "annotation"
28
+ SRC_OBJECT_ID = "src_object_id"
29
+ CLASS_NAME = "class_name"
30
+ KEY = "key"
31
+ TAGS_JSON = "tags_json"
32
+ SRC_FIGURE_ID = "src_figure_id"
33
+ FRAME_INDEX = "frame_index"
34
+ GEOMETRY_TYPE = "geometry_type"
35
+ GEOMETRY_JSON = "geometry_json"
@@ -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
+ }