supervisely 6.73.439__py3-none-any.whl → 6.73.441__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/label.py +80 -3
- supervisely/api/annotation_api.py +8 -8
- supervisely/api/entity_annotation/figure_api.py +17 -0
- supervisely/api/image_api.py +68 -1
- supervisely/api/module_api.py +4 -0
- supervisely/api/video/video_figure_api.py +24 -11
- supervisely/nn/inference/inference.py +34 -18
- supervisely/nn/inference/tracking/bbox_tracking.py +5 -1
- supervisely/nn/inference/tracking/point_tracking.py +5 -1
- supervisely/nn/inference/tracking/tracker_interface.py +4 -0
- supervisely/nn/model/prediction.py +2 -1
- supervisely/nn/model/prediction_session.py +18 -7
- supervisely/nn/tracker/botsort_tracker.py +2 -2
- supervisely/nn/tracker/utils.py +4 -5
- supervisely/video_annotation/video_figure.py +38 -4
- {supervisely-6.73.439.dist-info → supervisely-6.73.441.dist-info}/METADATA +2 -1
- {supervisely-6.73.439.dist-info → supervisely-6.73.441.dist-info}/RECORD +21 -21
- {supervisely-6.73.439.dist-info → supervisely-6.73.441.dist-info}/LICENSE +0 -0
- {supervisely-6.73.439.dist-info → supervisely-6.73.441.dist-info}/WHEEL +0 -0
- {supervisely-6.73.439.dist-info → supervisely-6.73.441.dist-info}/entry_points.txt +0 -0
- {supervisely-6.73.439.dist-info → supervisely-6.73.441.dist-info}/top_level.txt +0 -0
supervisely/annotation/label.py
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
# docs
|
|
5
5
|
from __future__ import annotations
|
|
6
6
|
|
|
7
|
+
|
|
8
|
+
from supervisely.collection.str_enum import StrEnum
|
|
7
9
|
from copy import deepcopy
|
|
8
10
|
from typing import Dict, List, Optional, Tuple, Union
|
|
9
11
|
|
|
@@ -45,6 +47,47 @@ class LabelJsonFields:
|
|
|
45
47
|
""""""
|
|
46
48
|
SMART_TOOL_INPUT = "smartToolInput"
|
|
47
49
|
""""""
|
|
50
|
+
NN_CREATED = "nnCreated"
|
|
51
|
+
"""Flag indicating if the label was created by NN model or manually."""
|
|
52
|
+
NN_UPDATED = "nnUpdated"
|
|
53
|
+
"""Flag indicating if the label was corrected by NN model or manually."""
|
|
54
|
+
|
|
55
|
+
class LabelingStatus(StrEnum):
|
|
56
|
+
"""
|
|
57
|
+
Shows status of the label. Can be one of the following:
|
|
58
|
+
|
|
59
|
+
- AUTO: Specifies if the label was created by NN model.
|
|
60
|
+
- nn_created: True | Created by NN model
|
|
61
|
+
- nn_updated: True | Corrected by NN model
|
|
62
|
+
- MANUAL: Specifies if the label was created manually.
|
|
63
|
+
- nn_created: False | Manually created
|
|
64
|
+
- nn_updated: False | Not corrected by NN model
|
|
65
|
+
- CORRECTED: Specifies if the label was initially created by NN model and then manually corrected.
|
|
66
|
+
- nn_created: True | Created by NN model
|
|
67
|
+
- nn_updated: False | Manually corrected
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
AUTO = "auto"
|
|
71
|
+
MANUAL = "manual"
|
|
72
|
+
CORRECTED = "corrected"
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def to_flags(cls, status: LabelingStatus) -> Tuple[bool, bool]:
|
|
76
|
+
if status == cls.AUTO:
|
|
77
|
+
return True, True
|
|
78
|
+
elif status == cls.CORRECTED:
|
|
79
|
+
return True, False
|
|
80
|
+
else:
|
|
81
|
+
return False, False
|
|
82
|
+
|
|
83
|
+
@classmethod
|
|
84
|
+
def from_flags(cls, nn_created: bool, nn_updated: bool) -> LabelingStatus:
|
|
85
|
+
if nn_created and nn_updated:
|
|
86
|
+
return cls.AUTO
|
|
87
|
+
elif nn_created and not nn_updated:
|
|
88
|
+
return cls.CORRECTED
|
|
89
|
+
else:
|
|
90
|
+
return cls.MANUAL
|
|
48
91
|
|
|
49
92
|
|
|
50
93
|
class LabelBase:
|
|
@@ -65,6 +108,8 @@ class LabelBase:
|
|
|
65
108
|
:type smart_tool_input: dict, optional
|
|
66
109
|
:param sly_id: Label unique identifier.
|
|
67
110
|
:type sly_id: int, optional
|
|
111
|
+
:param status: Sets labeling status. Shows how label was created and corrected.
|
|
112
|
+
:type status: LabelingStatus, optional
|
|
68
113
|
|
|
69
114
|
:Usage example:
|
|
70
115
|
|
|
@@ -99,6 +144,7 @@ class LabelBase:
|
|
|
99
144
|
binding_key: Optional[str] = None,
|
|
100
145
|
smart_tool_input: Optional[Dict] = None,
|
|
101
146
|
sly_id: Optional[int] = None,
|
|
147
|
+
status: Optional[LabelingStatus] = None,
|
|
102
148
|
):
|
|
103
149
|
self._geometry = geometry
|
|
104
150
|
self._obj_class = obj_class
|
|
@@ -112,9 +158,14 @@ class LabelBase:
|
|
|
112
158
|
|
|
113
159
|
self._binding_key = binding_key
|
|
114
160
|
self._smart_tool_input = smart_tool_input
|
|
115
|
-
|
|
116
161
|
self._sly_id = sly_id
|
|
117
162
|
|
|
163
|
+
if status is None:
|
|
164
|
+
status = LabelingStatus.MANUAL
|
|
165
|
+
self._status = status
|
|
166
|
+
self._nn_created, self._nn_updated = LabelingStatus.to_flags(self.status)
|
|
167
|
+
|
|
168
|
+
|
|
118
169
|
def _validate_geometry(self):
|
|
119
170
|
"""
|
|
120
171
|
The function checks the name of the Object for compliance.
|
|
@@ -268,7 +319,9 @@ class LabelBase:
|
|
|
268
319
|
# "interior": []
|
|
269
320
|
# },
|
|
270
321
|
# "geometryType": "rectangle",
|
|
271
|
-
# "shape": "rectangle"
|
|
322
|
+
# "shape": "rectangle",
|
|
323
|
+
# "nnCreated": false,
|
|
324
|
+
# "nnUpdated": false
|
|
272
325
|
# }
|
|
273
326
|
"""
|
|
274
327
|
res = {
|
|
@@ -278,6 +331,8 @@ class LabelBase:
|
|
|
278
331
|
**self.geometry.to_json(),
|
|
279
332
|
GEOMETRY_TYPE: self.geometry.geometry_name(),
|
|
280
333
|
GEOMETRY_SHAPE: self.geometry.geometry_name(),
|
|
334
|
+
LabelJsonFields.NN_CREATED: self._nn_created,
|
|
335
|
+
LabelJsonFields.NN_UPDATED: self._nn_updated,
|
|
281
336
|
}
|
|
282
337
|
|
|
283
338
|
if self.obj_class.sly_id is not None:
|
|
@@ -328,7 +383,9 @@ class LabelBase:
|
|
|
328
383
|
"points": {
|
|
329
384
|
"exterior": [[100, 100], [900, 700]],
|
|
330
385
|
"interior": []
|
|
331
|
-
}
|
|
386
|
+
},
|
|
387
|
+
"nnCreated": false,
|
|
388
|
+
"nnUpdated": false
|
|
332
389
|
}
|
|
333
390
|
|
|
334
391
|
label_dog = sly.Label.from_json(data, meta)
|
|
@@ -352,6 +409,10 @@ class LabelBase:
|
|
|
352
409
|
binding_key = data.get(LabelJsonFields.INSTANCE_KEY)
|
|
353
410
|
smart_tool_input = data.get(LabelJsonFields.SMART_TOOL_INPUT)
|
|
354
411
|
|
|
412
|
+
nn_created = data.get(LabelJsonFields.NN_CREATED, False)
|
|
413
|
+
nn_updated = data.get(LabelJsonFields.NN_UPDATED, False)
|
|
414
|
+
status = LabelingStatus.from_flags(nn_created, nn_updated)
|
|
415
|
+
|
|
355
416
|
return cls(
|
|
356
417
|
geometry=geometry,
|
|
357
418
|
obj_class=obj_class,
|
|
@@ -360,6 +421,7 @@ class LabelBase:
|
|
|
360
421
|
binding_key=binding_key,
|
|
361
422
|
smart_tool_input=smart_tool_input,
|
|
362
423
|
sly_id=data.get(LabelJsonFields.ID),
|
|
424
|
+
status=status,
|
|
363
425
|
)
|
|
364
426
|
|
|
365
427
|
@property
|
|
@@ -441,6 +503,7 @@ class LabelBase:
|
|
|
441
503
|
description: Optional[str] = None,
|
|
442
504
|
binding_key: Optional[str] = None,
|
|
443
505
|
smart_tool_input: Optional[Dict] = None,
|
|
506
|
+
status: Optional[LabelingStatus] = None,
|
|
444
507
|
) -> LabelBase:
|
|
445
508
|
"""
|
|
446
509
|
Makes a copy of Label with new fields, if fields are given, otherwise it will use fields of the original Label.
|
|
@@ -457,6 +520,8 @@ class LabelBase:
|
|
|
457
520
|
:type binding_key: str, optional
|
|
458
521
|
:param smart_tool_input: Smart Tool parameters that were used for labeling.
|
|
459
522
|
:type smart_tool_input: dict, optional
|
|
523
|
+
:param status: Sets labeling status. Specifies if the label was created by NN model, manually or created by NN and then manually corrected.
|
|
524
|
+
:type status: LabelingStatus, optional
|
|
460
525
|
:return: New instance of Label
|
|
461
526
|
:rtype: :class:`Label<LabelBase>`
|
|
462
527
|
:Usage example:
|
|
@@ -501,6 +566,7 @@ class LabelBase:
|
|
|
501
566
|
description=take_with_default(description, self.description),
|
|
502
567
|
binding_key=take_with_default(binding_key, self.binding_key),
|
|
503
568
|
smart_tool_input=take_with_default(smart_tool_input, self._smart_tool_input),
|
|
569
|
+
status=take_with_default(status, self.status),
|
|
504
570
|
)
|
|
505
571
|
|
|
506
572
|
def crop(self, rect: Rectangle) -> List[LabelBase]:
|
|
@@ -864,6 +930,17 @@ class LabelBase:
|
|
|
864
930
|
def labeler_login(self):
|
|
865
931
|
return self.geometry.labeler_login
|
|
866
932
|
|
|
933
|
+
@property
|
|
934
|
+
def status(self) -> LabelingStatus:
|
|
935
|
+
"""Labeling status. Specifies if the Label was created by NN model, manually or created by NN and then manually corrected."""
|
|
936
|
+
return self._status
|
|
937
|
+
|
|
938
|
+
@status.setter
|
|
939
|
+
def status(self, status: LabelingStatus):
|
|
940
|
+
"""Set labeling status."""
|
|
941
|
+
self._status = status
|
|
942
|
+
self._nn_created, self._nn_updated = LabelingStatus.to_flags(self.status)
|
|
943
|
+
|
|
867
944
|
@classmethod
|
|
868
945
|
def _to_pixel_coordinate_system_json(cls, data: Dict, image_size: List[int]) -> Dict:
|
|
869
946
|
"""
|
|
@@ -1312,14 +1312,14 @@ class AnnotationApi(ModuleApi):
|
|
|
1312
1312
|
|
|
1313
1313
|
api.annotation.update_label(label_id, new_label)
|
|
1314
1314
|
"""
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
)
|
|
1315
|
+
payload = {
|
|
1316
|
+
ApiField.ID: label_id,
|
|
1317
|
+
ApiField.TAGS: [tag.to_json() for tag in label.tags],
|
|
1318
|
+
ApiField.GEOMETRY: label.geometry.to_json(),
|
|
1319
|
+
ApiField.NN_CREATED: label._nn_created,
|
|
1320
|
+
ApiField.NN_UPDATED: label._nn_updated,
|
|
1321
|
+
}
|
|
1322
|
+
self._api.post("figures.editInfo", payload)
|
|
1323
1323
|
|
|
1324
1324
|
def update_label_priority(self, label_id: int, priority: int) -> None:
|
|
1325
1325
|
"""Updates label's priority with given ID in Supervisely.
|
|
@@ -27,6 +27,7 @@ from supervisely._utils import batched, logger, run_coroutine
|
|
|
27
27
|
from supervisely.api.module_api import ApiField, ModuleApi, RemoveableBulkModuleApi
|
|
28
28
|
from supervisely.geometry.rectangle import Rectangle
|
|
29
29
|
from supervisely.video_annotation.key_id_map import KeyIdMap
|
|
30
|
+
from supervisely.annotation.label import LabelingStatus
|
|
30
31
|
|
|
31
32
|
|
|
32
33
|
class FigureInfo(NamedTuple):
|
|
@@ -221,6 +222,8 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
221
222
|
"meta",
|
|
222
223
|
"area",
|
|
223
224
|
"priority",
|
|
225
|
+
"nnCreated",
|
|
226
|
+
"nnUpdated",
|
|
224
227
|
]
|
|
225
228
|
return self._get_info_by_id(id, "figures.info", {ApiField.FIELDS: fields})
|
|
226
229
|
|
|
@@ -233,6 +236,7 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
233
236
|
geometry_type: str,
|
|
234
237
|
track_id: Optional[int] = None,
|
|
235
238
|
custom_data: Optional[dict] = None,
|
|
239
|
+
status: Optional[LabelingStatus] = None,
|
|
236
240
|
) -> int:
|
|
237
241
|
""""""
|
|
238
242
|
input_figure = {
|
|
@@ -242,6 +246,13 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
242
246
|
ApiField.GEOMETRY: geometry_json,
|
|
243
247
|
}
|
|
244
248
|
|
|
249
|
+
if status is None:
|
|
250
|
+
status = LabelingStatus.MANUAL
|
|
251
|
+
|
|
252
|
+
nn_created, nn_updated = LabelingStatus.to_flags(status)
|
|
253
|
+
input_figure[ApiField.NN_CREATED] = nn_created
|
|
254
|
+
input_figure[ApiField.NN_UPDATED] = nn_updated
|
|
255
|
+
|
|
245
256
|
if track_id is not None:
|
|
246
257
|
input_figure[ApiField.TRACK_ID] = track_id
|
|
247
258
|
|
|
@@ -376,6 +387,8 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
376
387
|
ApiField.AREA,
|
|
377
388
|
ApiField.PRIORITY,
|
|
378
389
|
ApiField.CUSTOM_DATA,
|
|
390
|
+
ApiField.NN_CREATED,
|
|
391
|
+
ApiField.NN_UPDATED,
|
|
379
392
|
]
|
|
380
393
|
figures_infos = self.get_list_all_pages(
|
|
381
394
|
"figures.list",
|
|
@@ -496,6 +509,8 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
496
509
|
ApiField.AREA,
|
|
497
510
|
ApiField.PRIORITY,
|
|
498
511
|
ApiField.CUSTOM_DATA,
|
|
512
|
+
ApiField.NN_CREATED,
|
|
513
|
+
ApiField.NN_UPDATED,
|
|
499
514
|
]
|
|
500
515
|
if skip_geometry is True:
|
|
501
516
|
fields = [x for x in fields if x != ApiField.GEOMETRY]
|
|
@@ -854,6 +869,8 @@ class FigureApi(RemoveableBulkModuleApi):
|
|
|
854
869
|
ApiField.AREA,
|
|
855
870
|
ApiField.PRIORITY,
|
|
856
871
|
ApiField.CUSTOM_DATA,
|
|
872
|
+
ApiField.NN_CREATED,
|
|
873
|
+
ApiField.NN_UPDATED,
|
|
857
874
|
]
|
|
858
875
|
if skip_geometry is True:
|
|
859
876
|
fields = [x for x in fields if x != ApiField.GEOMETRY]
|
supervisely/api/image_api.py
CHANGED
|
@@ -70,7 +70,11 @@ from supervisely.api.module_api import (
|
|
|
70
70
|
_get_single_item,
|
|
71
71
|
)
|
|
72
72
|
from supervisely.imaging import image as sly_image
|
|
73
|
-
from supervisely.io.env import
|
|
73
|
+
from supervisely.io.env import (
|
|
74
|
+
add_uploaded_ids_to_env,
|
|
75
|
+
app_categories,
|
|
76
|
+
increment_upload_count,
|
|
77
|
+
)
|
|
74
78
|
from supervisely.io.fs import (
|
|
75
79
|
OFFSETS_PKL_BATCH_SIZE,
|
|
76
80
|
OFFSETS_PKL_SUFFIX,
|
|
@@ -5519,3 +5523,66 @@ class ImageApi(RemoveableBulkModuleApi):
|
|
|
5519
5523
|
method,
|
|
5520
5524
|
{ApiField.IMAGES: images},
|
|
5521
5525
|
)
|
|
5526
|
+
|
|
5527
|
+
def get_subsequent_image_ids(
|
|
5528
|
+
self,
|
|
5529
|
+
image_id: int,
|
|
5530
|
+
images_count: Optional[int] = None,
|
|
5531
|
+
job_id: Optional[int] = None,
|
|
5532
|
+
params: Optional[dict] = None,
|
|
5533
|
+
dataset_id: Optional[int] = None,
|
|
5534
|
+
project_id: Optional[int] = None,
|
|
5535
|
+
) -> List[int]:
|
|
5536
|
+
"""
|
|
5537
|
+
Get list of subsequent image IDs after the specified image ID.
|
|
5538
|
+
|
|
5539
|
+
:param image_id: Image ID in Supervisely.
|
|
5540
|
+
:type image_id: int
|
|
5541
|
+
:param images_count: Number of subsequent images to retrieve. If None, retrieves all subsequent images.
|
|
5542
|
+
:type images_count: int, optional
|
|
5543
|
+
:param job_id: Job ID to filter images. If None, does not filter by job ID.
|
|
5544
|
+
:type job_id: int, optional
|
|
5545
|
+
:param params: Additional parameters for filtering and sorting images.
|
|
5546
|
+
:type params: dict, optional
|
|
5547
|
+
:param dataset_id: Dataset ID to filter images.
|
|
5548
|
+
:type dataset_id: int, optional
|
|
5549
|
+
:param project_id: Project ID to filter images. If None, makes a request to retrieve it from the specified image.
|
|
5550
|
+
:type project_id: int, optional
|
|
5551
|
+
"""
|
|
5552
|
+
data = {
|
|
5553
|
+
"recursive": True,
|
|
5554
|
+
"projectId": project_id,
|
|
5555
|
+
"filters": [],
|
|
5556
|
+
"sort": "name",
|
|
5557
|
+
"sort_order": "asc",
|
|
5558
|
+
}
|
|
5559
|
+
|
|
5560
|
+
if params is not None:
|
|
5561
|
+
data.update(params)
|
|
5562
|
+
|
|
5563
|
+
if data["projectId"] is None:
|
|
5564
|
+
image_info = self.get_info_by_id(image_id)
|
|
5565
|
+
if image_info is None:
|
|
5566
|
+
raise ValueError(f"Image with ID {image_id} not found.")
|
|
5567
|
+
project_id = self._api.dataset.get_info_by_id(image_info.dataset_id).project_id
|
|
5568
|
+
if job_id is not None:
|
|
5569
|
+
self._api.add_header("x-job-id", str(job_id))
|
|
5570
|
+
if dataset_id is not None:
|
|
5571
|
+
data["datasetId"] = dataset_id
|
|
5572
|
+
|
|
5573
|
+
image_infos = self.get_list_all_pages(
|
|
5574
|
+
"images.list",
|
|
5575
|
+
data,
|
|
5576
|
+
limit=None,
|
|
5577
|
+
return_first_response=False,
|
|
5578
|
+
)
|
|
5579
|
+
self._api.headers.pop("x-job-id", None)
|
|
5580
|
+
image_ids = [img_info.id for img_info in image_infos]
|
|
5581
|
+
if len(image_ids) == 0:
|
|
5582
|
+
raise ValueError("No images found with the specified criteria.")
|
|
5583
|
+
elif image_id not in image_ids:
|
|
5584
|
+
raise ValueError(f"Image with ID {image_id} not found in the specified entity.")
|
|
5585
|
+
|
|
5586
|
+
target_idx = image_ids.index(image_id) + 1
|
|
5587
|
+
to_idx = target_idx + images_count if images_count is not None else len(image_ids)
|
|
5588
|
+
return image_ids[target_idx:to_idx]
|
supervisely/api/module_api.py
CHANGED
|
@@ -10,7 +10,7 @@ from supervisely.api.module_api import ApiField
|
|
|
10
10
|
from supervisely.geometry.geometry import Geometry
|
|
11
11
|
from supervisely.video_annotation.key_id_map import KeyIdMap
|
|
12
12
|
from supervisely.video_annotation.video_figure import VideoFigure
|
|
13
|
-
|
|
13
|
+
from supervisely.annotation.label import LabelingStatus
|
|
14
14
|
|
|
15
15
|
class VideoFigureApi(FigureApi):
|
|
16
16
|
"""
|
|
@@ -26,6 +26,7 @@ class VideoFigureApi(FigureApi):
|
|
|
26
26
|
geometry_type: str,
|
|
27
27
|
track_id: Optional[int] = None,
|
|
28
28
|
meta: Optional[dict] = None,
|
|
29
|
+
status: Optional[LabelingStatus] = None,
|
|
29
30
|
) -> int:
|
|
30
31
|
"""
|
|
31
32
|
Create new VideoFigure for given frame in given video ID.
|
|
@@ -42,6 +43,10 @@ class VideoFigureApi(FigureApi):
|
|
|
42
43
|
:type geometry_type: str
|
|
43
44
|
:param track_id: int, optional.
|
|
44
45
|
:type track_id: int, optional
|
|
46
|
+
:param meta: Meta data for VideoFigure.
|
|
47
|
+
:type meta: dict, optional
|
|
48
|
+
:param status: Labeling status. Specifies if the VideoFigure was created by NN model, manually or created by NN and then manually corrected.
|
|
49
|
+
:type status: LabelingStatus, optional
|
|
45
50
|
:return: New figure ID
|
|
46
51
|
:rtype: :class:`int`
|
|
47
52
|
:Usage example:
|
|
@@ -64,13 +69,16 @@ class VideoFigureApi(FigureApi):
|
|
|
64
69
|
"""
|
|
65
70
|
if meta is None:
|
|
66
71
|
meta = {}
|
|
72
|
+
meta = {**(meta or {}), ApiField.FRAME: frame_index}
|
|
73
|
+
|
|
67
74
|
return super().create(
|
|
68
75
|
video_id,
|
|
69
76
|
object_id,
|
|
70
|
-
|
|
77
|
+
meta,
|
|
71
78
|
geometry_json,
|
|
72
79
|
geometry_type,
|
|
73
80
|
track_id,
|
|
81
|
+
status=status,
|
|
74
82
|
)
|
|
75
83
|
|
|
76
84
|
def append_bulk(self, video_id: int, figures: List[VideoFigure], key_id_map: KeyIdMap) -> None:
|
|
@@ -115,13 +123,15 @@ class VideoFigureApi(FigureApi):
|
|
|
115
123
|
|
|
116
124
|
self._append_bulk(video_id, figures_json, keys, key_id_map)
|
|
117
125
|
|
|
118
|
-
def update(self, figure_id: int, geometry: Geometry) -> None:
|
|
126
|
+
def update(self, figure_id: int, geometry: Geometry, status: Optional[LabelingStatus] = None) -> None:
|
|
119
127
|
"""Updates figure feometry with given ID in Supervisely with new Geometry object.
|
|
120
128
|
|
|
121
129
|
:param figure_id: ID of the figure to update
|
|
122
130
|
:type figure_id: int
|
|
123
131
|
:param geometry: Supervisely Gepmetry object
|
|
124
132
|
:type geometry: Geometry
|
|
133
|
+
:param status: Labeling status. Specifies if the VideoFigure was created by NN model, manually or created by NN and then manually corrected.
|
|
134
|
+
:type status: LabelingStatus, optional
|
|
125
135
|
:Usage example:
|
|
126
136
|
|
|
127
137
|
.. code-block:: python
|
|
@@ -141,13 +151,17 @@ class VideoFigureApi(FigureApi):
|
|
|
141
151
|
|
|
142
152
|
api.video.figure.update(figure_id, new_geometry)
|
|
143
153
|
"""
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
payload = {
|
|
155
|
+
ApiField.ID: figure_id,
|
|
156
|
+
ApiField.GEOMETRY: geometry.to_json(),
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if status is not None:
|
|
160
|
+
nn_created,nn_updated = LabelingStatus.to_flags(status)
|
|
161
|
+
payload[ApiField.NN_CREATED] = nn_created
|
|
162
|
+
payload[ApiField.NN_UPDATED] = nn_updated
|
|
163
|
+
|
|
164
|
+
self._api.post("figures.editInfo", payload)
|
|
151
165
|
|
|
152
166
|
def download(
|
|
153
167
|
self, dataset_id: int, video_ids: List[int] = None, skip_geometry: bool = False, **kwargs
|
|
@@ -161,7 +175,6 @@ class VideoFigureApi(FigureApi):
|
|
|
161
175
|
:type video_ids: List[int], optional
|
|
162
176
|
:param skip_geometry: Skip the download of figure geometry. May be useful for a significant api request speed increase in the large datasets.
|
|
163
177
|
:type skip_geometry: bool
|
|
164
|
-
|
|
165
178
|
:return: A dictionary where keys are video IDs and values are lists of figures.
|
|
166
179
|
:rtype: :class: `Dict[int, List[FigureInfo]]`
|
|
167
180
|
"""
|
|
@@ -45,7 +45,7 @@ from supervisely._utils import (
|
|
|
45
45
|
rand_str,
|
|
46
46
|
)
|
|
47
47
|
from supervisely.annotation.annotation import Annotation
|
|
48
|
-
from supervisely.annotation.label import Label
|
|
48
|
+
from supervisely.annotation.label import Label, LabelingStatus
|
|
49
49
|
from supervisely.annotation.obj_class import ObjClass
|
|
50
50
|
from supervisely.annotation.tag_collection import TagCollection
|
|
51
51
|
from supervisely.annotation.tag_meta import TagMeta, TagValueType
|
|
@@ -1269,16 +1269,16 @@ class Inference:
|
|
|
1269
1269
|
|
|
1270
1270
|
def get_classes(self) -> List[str]:
|
|
1271
1271
|
return self.classes
|
|
1272
|
-
|
|
1272
|
+
|
|
1273
1273
|
def _tracker_init(self, tracker: str, tracker_settings: dict):
|
|
1274
1274
|
# Check if tracking is supported for this model
|
|
1275
1275
|
info = self.get_info()
|
|
1276
1276
|
tracking_support = info.get("tracking_on_videos_support", False)
|
|
1277
|
-
|
|
1277
|
+
|
|
1278
1278
|
if not tracking_support:
|
|
1279
1279
|
logger.debug("Tracking is not supported for this model")
|
|
1280
1280
|
return None
|
|
1281
|
-
|
|
1281
|
+
|
|
1282
1282
|
if tracker == "botsort":
|
|
1283
1283
|
from supervisely.nn.tracker import BotSortTracker
|
|
1284
1284
|
device = tracker_settings.get("device", self.device)
|
|
@@ -1289,7 +1289,6 @@ class Inference:
|
|
|
1289
1289
|
logger.warning(f"Unknown tracking type: {tracker}. Tracking is disabled.")
|
|
1290
1290
|
return None
|
|
1291
1291
|
|
|
1292
|
-
|
|
1293
1292
|
def get_info(self) -> Dict[str, Any]:
|
|
1294
1293
|
num_classes = None
|
|
1295
1294
|
classes = None
|
|
@@ -1439,8 +1438,12 @@ class Inference:
|
|
|
1439
1438
|
# for example empty mask
|
|
1440
1439
|
continue
|
|
1441
1440
|
if isinstance(label, list):
|
|
1441
|
+
for lb in label:
|
|
1442
|
+
lb.status = LabelingStatus.AUTO
|
|
1442
1443
|
labels.extend(label)
|
|
1443
1444
|
continue
|
|
1445
|
+
|
|
1446
|
+
label.status = LabelingStatus.AUTO
|
|
1444
1447
|
labels.append(label)
|
|
1445
1448
|
|
|
1446
1449
|
# create annotation with correct image resolution
|
|
@@ -1872,7 +1875,7 @@ class Inference:
|
|
|
1872
1875
|
n_frames = frames_reader.frames_count()
|
|
1873
1876
|
|
|
1874
1877
|
self._tracker = self._tracker_init(state.get("tracker", None), state.get("tracker_settings", {}))
|
|
1875
|
-
|
|
1878
|
+
|
|
1876
1879
|
progress_total = (n_frames + step - 1) // step
|
|
1877
1880
|
inference_request.set_stage(InferenceRequest.Stage.INFERENCE, 0, progress_total)
|
|
1878
1881
|
|
|
@@ -1896,32 +1899,31 @@ class Inference:
|
|
|
1896
1899
|
source=frames,
|
|
1897
1900
|
settings=inference_settings,
|
|
1898
1901
|
)
|
|
1899
|
-
|
|
1902
|
+
|
|
1900
1903
|
if self._tracker is not None:
|
|
1901
1904
|
anns = self._apply_tracker_to_anns(frames, anns)
|
|
1902
|
-
|
|
1905
|
+
|
|
1903
1906
|
predictions = [
|
|
1904
1907
|
Prediction(ann, model_meta=self.model_meta, frame_index=frame_index)
|
|
1905
1908
|
for ann, frame_index in zip(anns, batch)
|
|
1906
1909
|
]
|
|
1907
|
-
|
|
1910
|
+
|
|
1908
1911
|
for pred, this_slides_data in zip(predictions, slides_data):
|
|
1909
1912
|
pred.extra_data["slides_data"] = this_slides_data
|
|
1910
1913
|
batch_results = self._format_output(predictions)
|
|
1911
|
-
|
|
1914
|
+
|
|
1912
1915
|
inference_request.add_results(batch_results)
|
|
1913
1916
|
inference_request.done(len(batch_results))
|
|
1914
1917
|
logger.debug(f"Frames {batch[0]}-{batch[-1]} done.")
|
|
1915
1918
|
video_ann_json = None
|
|
1916
1919
|
if self._tracker is not None:
|
|
1917
1920
|
inference_request.set_stage("Postprocess...", 0, 1)
|
|
1918
|
-
|
|
1921
|
+
|
|
1919
1922
|
video_ann_json = self._tracker.video_annotation.to_json()
|
|
1920
1923
|
inference_request.done()
|
|
1921
1924
|
result = {"ann": results, "video_ann": video_ann_json}
|
|
1922
1925
|
inference_request.final_result = result.copy()
|
|
1923
1926
|
return video_ann_json
|
|
1924
|
-
|
|
1925
1927
|
|
|
1926
1928
|
def _inference_image_ids(
|
|
1927
1929
|
self,
|
|
@@ -2102,7 +2104,7 @@ class Inference:
|
|
|
2102
2104
|
n_frames = video_info.frames_count
|
|
2103
2105
|
|
|
2104
2106
|
self._tracker = self._tracker_init(state.get("tracker", None), state.get("tracker_settings", {}))
|
|
2105
|
-
|
|
2107
|
+
|
|
2106
2108
|
logger.debug(
|
|
2107
2109
|
f"Video info:",
|
|
2108
2110
|
extra=dict(
|
|
@@ -2137,10 +2139,10 @@ class Inference:
|
|
|
2137
2139
|
source=frames,
|
|
2138
2140
|
settings=inference_settings,
|
|
2139
2141
|
)
|
|
2140
|
-
|
|
2142
|
+
|
|
2141
2143
|
if self._tracker is not None:
|
|
2142
2144
|
anns = self._apply_tracker_to_anns(frames, anns)
|
|
2143
|
-
|
|
2145
|
+
|
|
2144
2146
|
predictions = [
|
|
2145
2147
|
Prediction(
|
|
2146
2148
|
ann,
|
|
@@ -2155,7 +2157,7 @@ class Inference:
|
|
|
2155
2157
|
for pred, this_slides_data in zip(predictions, slides_data):
|
|
2156
2158
|
pred.extra_data["slides_data"] = this_slides_data
|
|
2157
2159
|
batch_results = self._format_output(predictions)
|
|
2158
|
-
|
|
2160
|
+
|
|
2159
2161
|
inference_request.add_results(batch_results)
|
|
2160
2162
|
inference_request.done(len(batch_results))
|
|
2161
2163
|
logger.debug(f"Frames {batch[0]}-{batch[-1]} done.")
|
|
@@ -2637,6 +2639,10 @@ class Inference:
|
|
|
2637
2639
|
for prediction in predictions:
|
|
2638
2640
|
ds_predictions[prediction.dataset_id].append(prediction)
|
|
2639
2641
|
|
|
2642
|
+
def update_labeling_status(ann: Annotation) -> Annotation:
|
|
2643
|
+
for label in ann.labels:
|
|
2644
|
+
label.status = LabelingStatus.AUTO
|
|
2645
|
+
|
|
2640
2646
|
def _new_name(image_info: ImageInfo):
|
|
2641
2647
|
name = Path(image_info.name)
|
|
2642
2648
|
stem = name.stem
|
|
@@ -2712,8 +2718,15 @@ class Inference:
|
|
|
2712
2718
|
iou=iou_merge_threshold,
|
|
2713
2719
|
meta=project_meta,
|
|
2714
2720
|
)
|
|
2721
|
+
|
|
2722
|
+
# Update labeling status of new predictions before upload
|
|
2723
|
+
anns_with_nn_flags = []
|
|
2715
2724
|
for pred, ann in zip(preds, anns):
|
|
2725
|
+
update_labeling_status(ann)
|
|
2716
2726
|
pred.annotation = ann
|
|
2727
|
+
anns_with_nn_flags.append(ann)
|
|
2728
|
+
|
|
2729
|
+
anns = anns_with_nn_flags
|
|
2717
2730
|
|
|
2718
2731
|
context.setdefault("image_info", {})
|
|
2719
2732
|
missing = [
|
|
@@ -2778,7 +2791,10 @@ class Inference:
|
|
|
2778
2791
|
iou=iou_merge_threshold,
|
|
2779
2792
|
meta=project_meta,
|
|
2780
2793
|
)
|
|
2794
|
+
|
|
2795
|
+
# Update labeling status of predicted labels before optional merge
|
|
2781
2796
|
for pred, ann in zip(preds, anns):
|
|
2797
|
+
update_labeling_status(ann)
|
|
2782
2798
|
pred.annotation = ann
|
|
2783
2799
|
|
|
2784
2800
|
if upload_mode in ["iou_merge", "append"]:
|
|
@@ -4141,14 +4157,14 @@ class Inference:
|
|
|
4141
4157
|
matches = self._tracker.update(frame, ann)
|
|
4142
4158
|
track_ids = [match["track_id"] for match in matches]
|
|
4143
4159
|
tracked_labels = [match["label"] for match in matches]
|
|
4144
|
-
|
|
4160
|
+
|
|
4145
4161
|
filtered_annotation = ann.clone(
|
|
4146
4162
|
labels=tracked_labels,
|
|
4147
4163
|
custom_data=track_ids
|
|
4148
4164
|
)
|
|
4149
4165
|
updated_anns.append(filtered_annotation)
|
|
4150
4166
|
return updated_anns
|
|
4151
|
-
|
|
4167
|
+
|
|
4152
4168
|
def _add_workflow_input(self, model_source: str, model_files: dict, model_info: dict):
|
|
4153
4169
|
if model_source == ModelSource.PRETRAINED:
|
|
4154
4170
|
checkpoint_url = model_info["meta"]["model_files"]["checkpoint"]
|
|
@@ -7,7 +7,7 @@ import numpy as np
|
|
|
7
7
|
from pydantic import ValidationError
|
|
8
8
|
|
|
9
9
|
from supervisely.annotation.annotation import Annotation
|
|
10
|
-
from supervisely.annotation.label import Geometry, Label
|
|
10
|
+
from supervisely.annotation.label import Geometry, Label, LabelingStatus
|
|
11
11
|
from supervisely.annotation.obj_class import ObjClass
|
|
12
12
|
from supervisely.api.api import Api
|
|
13
13
|
from supervisely.api.module_api import ApiField
|
|
@@ -588,8 +588,12 @@ class BBoxTracking(BaseTracking):
|
|
|
588
588
|
# for example empty mask
|
|
589
589
|
continue
|
|
590
590
|
if isinstance(label, list):
|
|
591
|
+
for lb in label:
|
|
592
|
+
lb.status = LabelingStatus.AUTO
|
|
591
593
|
labels.extend(label)
|
|
592
594
|
continue
|
|
595
|
+
|
|
596
|
+
label.status = LabelingStatus.AUTO
|
|
593
597
|
labels.append(label)
|
|
594
598
|
|
|
595
599
|
# create annotation with correct image resolution
|
|
@@ -10,7 +10,7 @@ from pydantic import ValidationError
|
|
|
10
10
|
|
|
11
11
|
import supervisely.nn.inference.tracking.functional as F
|
|
12
12
|
from supervisely.annotation.annotation import Annotation
|
|
13
|
-
from supervisely.annotation.label import Geometry, Label
|
|
13
|
+
from supervisely.annotation.label import Geometry, Label, LabelingStatus
|
|
14
14
|
from supervisely.annotation.obj_class import ObjClass
|
|
15
15
|
from supervisely.api.api import Api
|
|
16
16
|
from supervisely.api.module_api import ApiField
|
|
@@ -610,8 +610,12 @@ class PointTracking(BaseTracking):
|
|
|
610
610
|
# for example empty mask
|
|
611
611
|
continue
|
|
612
612
|
if isinstance(label, list):
|
|
613
|
+
for lb in label:
|
|
614
|
+
lb.status = LabelingStatus.AUTO
|
|
613
615
|
labels.extend(label)
|
|
614
616
|
continue
|
|
617
|
+
|
|
618
|
+
label.status = LabelingStatus.AUTO
|
|
615
619
|
labels.append(label)
|
|
616
620
|
|
|
617
621
|
# create annotation with correct image resolution
|
|
@@ -22,6 +22,7 @@ from supervisely.geometry.rectangle import Rectangle
|
|
|
22
22
|
from supervisely.nn.inference.cache import InferenceImageCache
|
|
23
23
|
from supervisely.sly_logger import logger
|
|
24
24
|
from supervisely.video_annotation.key_id_map import KeyIdMap
|
|
25
|
+
from supervisely.annotation.label import LabelingStatus
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
class TrackerInterface:
|
|
@@ -166,6 +167,8 @@ class TrackerInterface:
|
|
|
166
167
|
ApiField.GEOMETRY: geometry.to_json(),
|
|
167
168
|
ApiField.META: {ApiField.FRAME: frame_index},
|
|
168
169
|
ApiField.TRACK_ID: self.track_id,
|
|
170
|
+
ApiField.NN_CREATED: True,
|
|
171
|
+
ApiField.NN_UPDATED: True,
|
|
169
172
|
}
|
|
170
173
|
for geometry, frame_index in geometries_frame_indexes
|
|
171
174
|
]
|
|
@@ -195,6 +198,7 @@ class TrackerInterface:
|
|
|
195
198
|
geometry.to_json(),
|
|
196
199
|
geometry.geometry_name(),
|
|
197
200
|
self.track_id,
|
|
201
|
+
status=LabelingStatus.AUTO,
|
|
198
202
|
)
|
|
199
203
|
self.logger.debug(f"Added {geometry.geometry_name()} to frame #{frame_ind}")
|
|
200
204
|
if notify:
|
|
@@ -59,6 +59,7 @@ class Prediction:
|
|
|
59
59
|
self.source = source
|
|
60
60
|
if isinstance(annotation_json, Annotation):
|
|
61
61
|
annotation_json = annotation_json.to_json()
|
|
62
|
+
|
|
62
63
|
self.annotation_json = annotation_json
|
|
63
64
|
self.model_meta = model_meta
|
|
64
65
|
if isinstance(self.model_meta, dict):
|
|
@@ -157,7 +158,7 @@ class Prediction:
|
|
|
157
158
|
|
|
158
159
|
@property
|
|
159
160
|
def annotation(self) -> Annotation:
|
|
160
|
-
if self._annotation is None:
|
|
161
|
+
if self._annotation is None and self.annotation_json is not None:
|
|
161
162
|
if self.model_meta is None:
|
|
162
163
|
raise ValueError("Model meta is not provided. Cannot create annotation.")
|
|
163
164
|
model_meta = get_meta_from_annotation(self.annotation_json, self.model_meta)
|
|
@@ -71,7 +71,7 @@ class PredictionSession:
|
|
|
71
71
|
tracking_config: dict = None,
|
|
72
72
|
**kwargs: dict,
|
|
73
73
|
):
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
extra_input_args = ["image_ids", "video_ids", "dataset_ids", "project_ids"]
|
|
76
76
|
assert (
|
|
77
77
|
sum(
|
|
@@ -90,7 +90,6 @@ class PredictionSession:
|
|
|
90
90
|
== 1
|
|
91
91
|
), "Exactly one of input, image_ids, video_id, dataset_id, project_id or image_id must be provided."
|
|
92
92
|
|
|
93
|
-
|
|
94
93
|
self._iterator = None
|
|
95
94
|
self._base_url = url
|
|
96
95
|
self.inference_request_uuid = None
|
|
@@ -115,12 +114,12 @@ class PredictionSession:
|
|
|
115
114
|
self.inference_settings = {
|
|
116
115
|
k: v for k, v in kwargs.items() if isinstance(v, (str, int, float))
|
|
117
116
|
}
|
|
118
|
-
|
|
117
|
+
|
|
119
118
|
if tracking is True:
|
|
120
119
|
model_info = self._get_session_info()
|
|
121
120
|
if not model_info.get("tracking_on_videos_support", False):
|
|
122
121
|
raise ValueError("Tracking is not supported by this model")
|
|
123
|
-
|
|
122
|
+
|
|
124
123
|
if tracking_config is None:
|
|
125
124
|
self.tracker = "botsort"
|
|
126
125
|
self.tracker_settings = {}
|
|
@@ -286,7 +285,7 @@ class PredictionSession:
|
|
|
286
285
|
if self.api is not None:
|
|
287
286
|
return self.api.token
|
|
288
287
|
return env.api_token(raise_not_found=False)
|
|
289
|
-
|
|
288
|
+
|
|
290
289
|
def _get_json_body(self):
|
|
291
290
|
body = {"state": {}, "context": {}}
|
|
292
291
|
if self.inference_request_uuid is not None:
|
|
@@ -298,7 +297,7 @@ class PredictionSession:
|
|
|
298
297
|
if "model_prediction_suffix" in self.kwargs:
|
|
299
298
|
body["state"]["model_prediction_suffix"] = self.kwargs["model_prediction_suffix"]
|
|
300
299
|
return body
|
|
301
|
-
|
|
300
|
+
|
|
302
301
|
def _post(self, method, *args, retries=5, **kwargs) -> requests.Response:
|
|
303
302
|
if kwargs.get("headers") is None:
|
|
304
303
|
kwargs["headers"] = {}
|
|
@@ -336,7 +335,7 @@ class PredictionSession:
|
|
|
336
335
|
method = "get_session_info"
|
|
337
336
|
r = self._post(method, json=self._get_json_body())
|
|
338
337
|
return r.json()
|
|
339
|
-
|
|
338
|
+
|
|
340
339
|
def _get_inference_progress(self):
|
|
341
340
|
method = "get_inference_progress"
|
|
342
341
|
r = self._post(method, json=self._get_json_body())
|
|
@@ -365,9 +364,21 @@ class PredictionSession:
|
|
|
365
364
|
logger.info("Inference request will be cleared on the server")
|
|
366
365
|
return r.json()
|
|
367
366
|
|
|
367
|
+
def _get_final_result(self):
|
|
368
|
+
method = "get_inference_result"
|
|
369
|
+
r = self._post(
|
|
370
|
+
method,
|
|
371
|
+
json=self._get_json_body(),
|
|
372
|
+
)
|
|
373
|
+
return r.json()
|
|
374
|
+
|
|
368
375
|
def _on_infernce_end(self):
|
|
369
376
|
if self.inference_request_uuid is None:
|
|
370
377
|
return
|
|
378
|
+
try:
|
|
379
|
+
self.final_result = self._get_final_result()
|
|
380
|
+
except Exception as e:
|
|
381
|
+
logger.debug("Failed to get final result:", exc_info=True)
|
|
371
382
|
self._clear_inference_request()
|
|
372
383
|
|
|
373
384
|
@property
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import supervisely as sly
|
|
2
2
|
from supervisely.nn.tracker.base_tracker import BaseTracker
|
|
3
3
|
from supervisely import Annotation, VideoAnnotation
|
|
4
|
-
|
|
4
|
+
from supervisely.annotation.label import LabelingStatus
|
|
5
5
|
from dataclasses import dataclass
|
|
6
6
|
from types import SimpleNamespace
|
|
7
7
|
from typing import List, Dict, Tuple, Any, Optional
|
|
@@ -239,7 +239,7 @@ class BotSortTracker(BaseTracker):
|
|
|
239
239
|
|
|
240
240
|
video_object = video_objects[track_id]
|
|
241
241
|
rect = sly.Rectangle(top=y1, left=x1, bottom=y2, right=x2)
|
|
242
|
-
frame_figures.append(sly.VideoFigure(video_object, rect, frame_idx, track_id=str(track_id)))
|
|
242
|
+
frame_figures.append(sly.VideoFigure(video_object, rect, frame_idx, track_id=str(track_id), status=LabelingStatus.AUTO))
|
|
243
243
|
|
|
244
244
|
frames.append(sly.Frame(frame_idx, frame_figures))
|
|
245
245
|
|
supervisely/nn/tracker/utils.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
from typing import List, Union, Dict, Tuple
|
|
3
2
|
from pathlib import Path
|
|
4
3
|
from collections import defaultdict
|
|
@@ -6,6 +5,7 @@ import numpy as np
|
|
|
6
5
|
|
|
7
6
|
import supervisely as sly
|
|
8
7
|
from supervisely.nn.model.prediction import Prediction
|
|
8
|
+
from supervisely.annotation.label import LabelingStatus
|
|
9
9
|
from supervisely import VideoAnnotation
|
|
10
10
|
from supervisely import logger
|
|
11
11
|
|
|
@@ -73,12 +73,11 @@ def predictions_to_video_annotation(
|
|
|
73
73
|
|
|
74
74
|
video_object = video_objects[track_id]
|
|
75
75
|
rect = sly.Rectangle(top=top, left=left, bottom=bottom, right=right)
|
|
76
|
-
frame_figures.append(sly.VideoFigure(video_object, rect, frame_idx, track_id=str(track_id)))
|
|
76
|
+
frame_figures.append(sly.VideoFigure(video_object, rect, frame_idx, track_id=str(track_id), status=LabelingStatus.AUTO))
|
|
77
77
|
|
|
78
78
|
frames.append(sly.Frame(frame_idx, frame_figures))
|
|
79
79
|
|
|
80
|
-
objects = list(video_objects.values())
|
|
81
|
-
|
|
80
|
+
objects = list(video_objects.values())
|
|
82
81
|
return VideoAnnotation(
|
|
83
82
|
img_size=frame_shape,
|
|
84
83
|
frames_count=len(predictions),
|
|
@@ -271,4 +270,4 @@ def mot_to_video_annotation(
|
|
|
271
270
|
|
|
272
271
|
logger.info(f"Created VideoAnnotation with {len(objects)} tracks and {frames_count} frames")
|
|
273
272
|
|
|
274
|
-
return annotation
|
|
273
|
+
return annotation
|
|
@@ -24,6 +24,8 @@ from supervisely.video_annotation.key_id_map import KeyIdMap
|
|
|
24
24
|
from supervisely.video_annotation.video_object import VideoObject
|
|
25
25
|
from supervisely.video_annotation.video_object_collection import VideoObjectCollection
|
|
26
26
|
|
|
27
|
+
from supervisely.annotation.label import LabelingStatus
|
|
28
|
+
|
|
27
29
|
|
|
28
30
|
class OutOfImageBoundsException(Exception):
|
|
29
31
|
pass
|
|
@@ -55,6 +57,8 @@ class VideoFigure:
|
|
|
55
57
|
:type smart_tool_input: dict, optional
|
|
56
58
|
:param priority: Priority of the figure (position of the figure relative to other overlapping or underlying figures).
|
|
57
59
|
:type priority: int, optional
|
|
60
|
+
:param status: Sets labeling status. Shows how label was created and corrected.
|
|
61
|
+
:type status: LabelingStatus, optional
|
|
58
62
|
:Usage example:
|
|
59
63
|
|
|
60
64
|
.. code-block:: python
|
|
@@ -86,7 +90,9 @@ class VideoFigure:
|
|
|
86
90
|
# ],
|
|
87
91
|
# "interior": []
|
|
88
92
|
# }
|
|
89
|
-
# }
|
|
93
|
+
# },
|
|
94
|
+
# "nnCreated": false,
|
|
95
|
+
# "nnUpdated": false
|
|
90
96
|
# }
|
|
91
97
|
"""
|
|
92
98
|
|
|
@@ -103,6 +109,7 @@ class VideoFigure:
|
|
|
103
109
|
track_id: Optional[str] = None,
|
|
104
110
|
smart_tool_input: Optional[Dict] = None,
|
|
105
111
|
priority: Optional[int] = None,
|
|
112
|
+
status: Optional[LabelingStatus] = None,
|
|
106
113
|
):
|
|
107
114
|
self._video_object = video_object
|
|
108
115
|
self._set_geometry_inplace(geometry)
|
|
@@ -116,6 +123,11 @@ class VideoFigure:
|
|
|
116
123
|
self._smart_tool_input = smart_tool_input
|
|
117
124
|
self._priority = priority
|
|
118
125
|
|
|
126
|
+
if status is None:
|
|
127
|
+
status = LabelingStatus.MANUAL
|
|
128
|
+
self._status = status
|
|
129
|
+
self._nn_created, self._nn_updated = LabelingStatus.to_flags(self.status)
|
|
130
|
+
|
|
119
131
|
def _add_creation_info(self, d):
|
|
120
132
|
if self.labeler_login is not None:
|
|
121
133
|
d[LABELER_LOGIN] = self.labeler_login
|
|
@@ -339,9 +351,9 @@ class VideoFigure:
|
|
|
339
351
|
# "interior": []
|
|
340
352
|
# }
|
|
341
353
|
# },
|
|
342
|
-
# "meta": {
|
|
343
|
-
#
|
|
344
|
-
#
|
|
354
|
+
# "meta": {"frame": 7},
|
|
355
|
+
# "nnCreated": false,
|
|
356
|
+
# "nnUpdated": false
|
|
345
357
|
# }
|
|
346
358
|
"""
|
|
347
359
|
data_json = {
|
|
@@ -349,6 +361,8 @@ class VideoFigure:
|
|
|
349
361
|
OBJECT_KEY: self.parent_object.key().hex,
|
|
350
362
|
ApiField.GEOMETRY_TYPE: self.geometry.geometry_name(),
|
|
351
363
|
ApiField.GEOMETRY: self.geometry.to_json(),
|
|
364
|
+
ApiField.NN_CREATED: self._nn_created,
|
|
365
|
+
ApiField.NN_UPDATED: self._nn_updated,
|
|
352
366
|
}
|
|
353
367
|
|
|
354
368
|
if key_id_map is not None:
|
|
@@ -473,6 +487,10 @@ class VideoFigure:
|
|
|
473
487
|
smart_tool_input = data.get(ApiField.SMART_TOOL_INPUT, None)
|
|
474
488
|
priority = data.get(ApiField.PRIORITY, None)
|
|
475
489
|
|
|
490
|
+
nn_created = data.get(ApiField.NN_CREATED, False)
|
|
491
|
+
nn_updated = data.get(ApiField.NN_UPDATED, False)
|
|
492
|
+
status = LabelingStatus.from_flags(nn_created, nn_updated)
|
|
493
|
+
|
|
476
494
|
return cls(
|
|
477
495
|
object,
|
|
478
496
|
geometry,
|
|
@@ -485,6 +503,7 @@ class VideoFigure:
|
|
|
485
503
|
track_id=track_id,
|
|
486
504
|
smart_tool_input=smart_tool_input,
|
|
487
505
|
priority=priority,
|
|
506
|
+
status=status,
|
|
488
507
|
)
|
|
489
508
|
|
|
490
509
|
def clone(
|
|
@@ -500,6 +519,7 @@ class VideoFigure:
|
|
|
500
519
|
track_id: Optional[str] = None,
|
|
501
520
|
smart_tool_input: Optional[Dict] = None,
|
|
502
521
|
priority: Optional[int] = None,
|
|
522
|
+
status: Optional[LabelingStatus] = None,
|
|
503
523
|
) -> VideoFigure:
|
|
504
524
|
"""
|
|
505
525
|
Makes a copy of VideoFigure with new fields, if fields are given, otherwise it will use fields of the original VideoFigure.
|
|
@@ -526,6 +546,8 @@ class VideoFigure:
|
|
|
526
546
|
:type smart_tool_input: dict, optional
|
|
527
547
|
:param priority: Priority of the figure (position of the figure relative to other overlapping or underlying figures).
|
|
528
548
|
:type priority: int, optional
|
|
549
|
+
:param status: Sets labeling status. Specifies if the VideoFigure was created by NN model, manually or created by NN and then manually corrected.
|
|
550
|
+
:type status: LabelingStatus, optional
|
|
529
551
|
:return: VideoFigure object
|
|
530
552
|
:rtype: :class:`VideoFigure`
|
|
531
553
|
|
|
@@ -582,8 +604,20 @@ class VideoFigure:
|
|
|
582
604
|
track_id=take_with_default(track_id, self.track_id),
|
|
583
605
|
smart_tool_input=take_with_default(smart_tool_input, self._smart_tool_input),
|
|
584
606
|
priority=take_with_default(priority, self._priority),
|
|
607
|
+
status=take_with_default(status, self.status),
|
|
585
608
|
)
|
|
586
609
|
|
|
610
|
+
@property
|
|
611
|
+
def status(self) -> LabelingStatus:
|
|
612
|
+
"""Labeling status. Specifies if the VideoFigure was created by NN model, manually or created by NN and then manually corrected."""
|
|
613
|
+
return self._status
|
|
614
|
+
|
|
615
|
+
@status.setter
|
|
616
|
+
def status(self, status: LabelingStatus):
|
|
617
|
+
"""Set labeling status."""
|
|
618
|
+
self._status = status
|
|
619
|
+
self._nn_created, self._nn_updated = LabelingStatus.to_flags(self.status)
|
|
620
|
+
|
|
587
621
|
def validate_bounds(
|
|
588
622
|
self, img_size: Tuple[int, int], _auto_correct: Optional[bool] = False
|
|
589
623
|
) -> None:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: supervisely
|
|
3
|
-
Version: 6.73.
|
|
3
|
+
Version: 6.73.441
|
|
4
4
|
Summary: Supervisely Python SDK.
|
|
5
5
|
Home-page: https://github.com/supervisely/supervisely
|
|
6
6
|
Author: Supervisely
|
|
@@ -131,6 +131,7 @@ Requires-Dist: tensorboard; extra == "tracking"
|
|
|
131
131
|
Requires-Dist: decord; extra == "tracking"
|
|
132
132
|
Requires-Dist: gdown; extra == "tracking"
|
|
133
133
|
Requires-Dist: torch; extra == "tracking"
|
|
134
|
+
Requires-Dist: motmetrics; extra == "tracking"
|
|
134
135
|
Provides-Extra: training
|
|
135
136
|
Requires-Dist: pycocotools; extra == "training"
|
|
136
137
|
Requires-Dist: scikit-learn; extra == "training"
|
|
@@ -9,7 +9,7 @@ supervisely/annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
9
9
|
supervisely/annotation/annotation.py,sha256=th4gsIU-LNGcMRohHrtupmjxDwdzx1g4_0xIAa6NyJU,114717
|
|
10
10
|
supervisely/annotation/annotation_transforms.py,sha256=TlVy_gUbM-XH6GbLpZPrAi6pMIGTr7Ow02iSKOSTa-I,9582
|
|
11
11
|
supervisely/annotation/json_geometries_map.py,sha256=nL6AmMhFy02fw9ryBm75plKyOkDh61QdOToSuLAcz_Q,1659
|
|
12
|
-
supervisely/annotation/label.py,sha256=
|
|
12
|
+
supervisely/annotation/label.py,sha256=sOK6lGDa-uSNCb7o4F9BJwnPia-Qp36OmFOU8oHyHPA,40601
|
|
13
13
|
supervisely/annotation/obj_class.py,sha256=W7-958-E9TfsL7eKAI3bbOvfAVxd3Unq-7F3lc2Gxjg,16672
|
|
14
14
|
supervisely/annotation/obj_class_collection.py,sha256=lsBJ8mElvwMHky2vsj4GfZ9_Uq186eS-o4ldoNeUJnw,12416
|
|
15
15
|
supervisely/annotation/obj_class_mapper.py,sha256=aIJDoRULqcAOD2a1CQPk2OOF8k3VPPSJQZdBAj71VQc,943
|
|
@@ -22,7 +22,7 @@ supervisely/annotation/tag_meta_mapper.py,sha256=RWeTrxJ64syodyhXIRSH007bX6Hr3B4
|
|
|
22
22
|
supervisely/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
23
|
supervisely/api/advanced_api.py,sha256=Nd5cCnHFWc3PSUrCtENxTGtDjS37_lCHXsgXvUI3Ti8,2054
|
|
24
24
|
supervisely/api/agent_api.py,sha256=8EQBwD6v7KLS0-xKcZ12B7mtzKwG7RRgq1fk1vaN144,8893
|
|
25
|
-
supervisely/api/annotation_api.py,sha256=
|
|
25
|
+
supervisely/api/annotation_api.py,sha256=TNOqVGE94FqDc7WDLBZiDY3aSIiyTQwn_bZv5_CIXBw,82970
|
|
26
26
|
supervisely/api/api.py,sha256=gRItQzO6Xj7k_pJIpVUS2dV1vkTTHV25_1Uia6xxZSc,67930
|
|
27
27
|
supervisely/api/app_api.py,sha256=Q6XxLxp3D_Vc3PIVyBmP7wJtTLbgYCPNOLND5UvJhMw,79010
|
|
28
28
|
supervisely/api/constants.py,sha256=WfqIcEpRnU4Mcfb6q0njeRs2VVSoTAJaIyrqBkBjP8I,253
|
|
@@ -31,12 +31,12 @@ supervisely/api/entities_collection_api.py,sha256=Be13HsfMFLmq9XpiOfQog0Y569kbUn
|
|
|
31
31
|
supervisely/api/file_api.py,sha256=gNXNsikocSYRojoZrVmXIqXycqXm0e320piAwaLN6JI,92978
|
|
32
32
|
supervisely/api/github_api.py,sha256=NIexNjEer9H5rf5sw2LEZd7C1WR-tK4t6IZzsgeAAwQ,623
|
|
33
33
|
supervisely/api/image_annotation_tool_api.py,sha256=YcUo78jRDBJYvIjrd-Y6FJAasLta54nnxhyaGyanovA,5237
|
|
34
|
-
supervisely/api/image_api.py,sha256=
|
|
34
|
+
supervisely/api/image_api.py,sha256=iDxY_PupkZ5CqnFkegcyLohGohE-6PEa6iiClkLIsC8,235489
|
|
35
35
|
supervisely/api/import_storage_api.py,sha256=BDCgmR0Hv6OoiRHLCVPKt3iDxSVlQp1WrnKhAK_Zl84,460
|
|
36
36
|
supervisely/api/issues_api.py,sha256=BqDJXmNoTzwc3xe6_-mA7FDFC5QQ-ahGbXk_HmpkSeQ,17925
|
|
37
37
|
supervisely/api/labeling_job_api.py,sha256=G2_BV_WtA2lAhfw_nAQmWmv1P-pwimD0ba9GVKoGjiA,55537
|
|
38
38
|
supervisely/api/labeling_queue_api.py,sha256=ilNjAL1d9NSa9yabQn6E-W26YdtooT3ZGXIFZtGnAvY,30158
|
|
39
|
-
supervisely/api/module_api.py,sha256=
|
|
39
|
+
supervisely/api/module_api.py,sha256=cs7kTsOTjI38iZRheFAcPjpFupjrGj5UOf0OaH-Fc_0,46538
|
|
40
40
|
supervisely/api/object_class_api.py,sha256=7-npNFMYjWNtSXYZg6syc6bX56_oCzDU2kFRPGQWCwA,10399
|
|
41
41
|
supervisely/api/plugin_api.py,sha256=SFm0IlTTOjuHBLUMgG4d4k6U3cWJocE-SVb-f08fwMQ,5286
|
|
42
42
|
supervisely/api/project_api.py,sha256=rZfPGwswx25-QXEgXwKIaCr5IEQJDA78s_2S92nAroY,104652
|
|
@@ -52,7 +52,7 @@ supervisely/api/video_annotation_tool_api.py,sha256=3A9-U8WJzrTShP_n9T8U01M9FzGY
|
|
|
52
52
|
supervisely/api/workspace_api.py,sha256=24O9uR5eIA2JdD0eQLi9LGaaHISdb2gUqnxJtx7bTew,9222
|
|
53
53
|
supervisely/api/entity_annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
supervisely/api/entity_annotation/entity_annotation_api.py,sha256=R7irdsYmUecsibuUFbcPRiS6tV3GnCHi9NfWeuoN7_0,3085
|
|
55
|
-
supervisely/api/entity_annotation/figure_api.py,sha256=
|
|
55
|
+
supervisely/api/entity_annotation/figure_api.py,sha256=DN0mL40ZIoDoVQtCoUfcff9AEKcAoKRYDi6zdHDR7rg,38652
|
|
56
56
|
supervisely/api/entity_annotation/object_api.py,sha256=gbcNvN_KY6G80Me8fHKQgryc2Co7VU_kfFd1GYILZ4E,8875
|
|
57
57
|
supervisely/api/entity_annotation/tag_api.py,sha256=IapvSZmakjdOn0yvqP2tQRY8gkZg0bcvIZBwWRcafrg,18996
|
|
58
58
|
supervisely/api/nn/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -72,7 +72,7 @@ supervisely/api/pointcloud/pointcloud_tag_api.py,sha256=iShtr052nOElxsyMyZEUT2vy
|
|
|
72
72
|
supervisely/api/video/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
73
|
supervisely/api/video/video_annotation_api.py,sha256=LAdZUC5qB6Q3ufDEUfWERYiglM3I_MYg9Yv1Nn6aKZ4,14137
|
|
74
74
|
supervisely/api/video/video_api.py,sha256=jeW-UjQt5xt7qQHOyTgFc5qe7SergCadxfeNgpLDx-I,95727
|
|
75
|
-
supervisely/api/video/video_figure_api.py,sha256=
|
|
75
|
+
supervisely/api/video/video_figure_api.py,sha256=T7mka1EG16NBlWezwQB0AeoEQrDDjf_MDPfe_eO9BVE,7107
|
|
76
76
|
supervisely/api/video/video_frame_api.py,sha256=4GwSI4xdCNYEUvTqzKc-Ewd44fw5zqkFoD24jrrN_aY,10214
|
|
77
77
|
supervisely/api/video/video_object_api.py,sha256=IC0NP8EoIT_d3xxDRgz2cA3ixSiuJ5ymy64eS-RfmDM,2227
|
|
78
78
|
supervisely/api/video/video_tag_api.py,sha256=wPe1HeJyg9kV1z2UJq6BEte5sKBoPJ2UGAHpGivis9c,14911
|
|
@@ -904,7 +904,7 @@ supervisely/nn/benchmark/visualization/widgets/table/__init__.py,sha256=47DEQpj8
|
|
|
904
904
|
supervisely/nn/benchmark/visualization/widgets/table/table.py,sha256=atmDnF1Af6qLQBUjLhK18RMDKAYlxnsuVHMSEa5a-e8,4319
|
|
905
905
|
supervisely/nn/inference/__init__.py,sha256=QFukX2ip-U7263aEPCF_UCFwj6EujbMnsgrXp5Bbt8I,1623
|
|
906
906
|
supervisely/nn/inference/cache.py,sha256=rfmb1teJ9lNDfisUSh6bwDCVkPZocn8GMvDgLQktnbo,35023
|
|
907
|
-
supervisely/nn/inference/inference.py,sha256=
|
|
907
|
+
supervisely/nn/inference/inference.py,sha256=sr70lji4u7V5MsZBiUBBUuc8_dL_FsNLboAPexAq0HU,203145
|
|
908
908
|
supervisely/nn/inference/inference_request.py,sha256=y6yw0vbaRRcEBS27nq3y0sL6Gmq2qLA_Bm0GrnJGegE,14267
|
|
909
909
|
supervisely/nn/inference/session.py,sha256=XUqJ_CqHk3ZJYkWxdnErN_6afCpIBU76nq6Ek7DiOQI,35792
|
|
910
910
|
supervisely/nn/inference/uploader.py,sha256=Dn5MfMRq7tclEWpP0B9fJjTiQPBpwumfXxC8-lOYgnM,5659
|
|
@@ -952,13 +952,13 @@ supervisely/nn/inference/semantic_segmentation/__init__.py,sha256=47DEQpj8HBSa-_
|
|
|
952
952
|
supervisely/nn/inference/semantic_segmentation/semantic_segmentation.py,sha256=xpmViSYm1v_ZxlYyqiD_DiB7_LEynv9ZoU0t2QHEx8A,3370
|
|
953
953
|
supervisely/nn/inference/tracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
954
954
|
supervisely/nn/inference/tracking/base_tracking.py,sha256=pAxmuiPyuMuwSaOkLedqSVnqiZjk2Wlt03kyiLl5oxA,12434
|
|
955
|
-
supervisely/nn/inference/tracking/bbox_tracking.py,sha256=
|
|
955
|
+
supervisely/nn/inference/tracking/bbox_tracking.py,sha256=ScEj9Ce3n-vIQsaNm9cGDy6KRKhvjQ1FUQ2CAVgjSyE,23914
|
|
956
956
|
supervisely/nn/inference/tracking/functional.py,sha256=LpVu2gvOOpr9D_uvwTPZey1wUCAhV-E20RPKmCSIrK4,1774
|
|
957
957
|
supervisely/nn/inference/tracking/mask_tracking.py,sha256=Sl7HzznNIvUmCfPporOqDa2kbSmeTvU1hSkLgeWg3kc,25499
|
|
958
958
|
supervisely/nn/inference/tracking/object_tracking_3d.py,sha256=Kqvx1qe1G8F1VtdBiy2HJ251rJU6s3LWhj0ZedhrmUw,4327
|
|
959
|
-
supervisely/nn/inference/tracking/point_tracking.py,sha256=
|
|
959
|
+
supervisely/nn/inference/tracking/point_tracking.py,sha256=8y20hzS8qDAZlAQhr-tLKUMyckklg-k1nyW6B8ZmG0k,24948
|
|
960
960
|
supervisely/nn/inference/tracking/tracker3d_interface.py,sha256=7yIkNO9rgkzQuyXUUccLwqlv5k7RPbxTqz9uI4FylLE,2781
|
|
961
|
-
supervisely/nn/inference/tracking/tracker_interface.py,sha256=
|
|
961
|
+
supervisely/nn/inference/tracking/tracker_interface.py,sha256=1zsOO0AVfT0kJk6QqxkMJe_imkMHom7FquzpcVD2j9Y,24228
|
|
962
962
|
supervisely/nn/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
963
963
|
supervisely/nn/legacy/config.py,sha256=TKdyGtURJKzKoyydCZAfujoUnbC0SO8GeVLTSnoyS_w,2994
|
|
964
964
|
supervisely/nn/legacy/dataset.py,sha256=-56EI6OYbkTWx4y8hOgD76y47zUoJNjGFyZ6JaP8iqg,6055
|
|
@@ -992,13 +992,13 @@ supervisely/nn/legacy/training/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5
|
|
|
992
992
|
supervisely/nn/legacy/training/eval_planner.py,sha256=zN9b0_CX7sWGdC8e6riTvD-NOUc3_Xduyhj00S7PEIo,1311
|
|
993
993
|
supervisely/nn/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
994
994
|
supervisely/nn/model/model_api.py,sha256=tSstGGdzm3cHc81P7IoM447sMVesUYJpspzMqUY70pg,10322
|
|
995
|
-
supervisely/nn/model/prediction.py,sha256=
|
|
996
|
-
supervisely/nn/model/prediction_session.py,sha256=
|
|
995
|
+
supervisely/nn/model/prediction.py,sha256=gt4c80LkcBFd5-a2iHpShPDTRO81MKHSWiBp47Gb1z0,11983
|
|
996
|
+
supervisely/nn/model/prediction_session.py,sha256=9fPECqnRJLqi2HCJINhDabB7IbgKWAMbDHIxt4RDJeE,27691
|
|
997
997
|
supervisely/nn/tracker/__init__.py,sha256=1Pv1zLedcZaTk1BS3ezscQbVizq7vQABlNbLhEhHkOI,326
|
|
998
998
|
supervisely/nn/tracker/base_tracker.py,sha256=2d23JlHizOqVye324YT20EE8RP52uwoQUkPYvPXJTdw,1668
|
|
999
|
-
supervisely/nn/tracker/botsort_tracker.py,sha256=
|
|
999
|
+
supervisely/nn/tracker/botsort_tracker.py,sha256=F2OaoeK1EAlBKAY95Fd9ZooZIlOZBh4YThhzmKNyP6w,10224
|
|
1000
1000
|
supervisely/nn/tracker/calculate_metrics.py,sha256=JjXI4VYWYSZ5j2Ed81FNYozkS3v2UAM73ztjLrHGg58,10434
|
|
1001
|
-
supervisely/nn/tracker/utils.py,sha256=
|
|
1001
|
+
supervisely/nn/tracker/utils.py,sha256=4WdtFHSEx5Buq6aND7cD21FdH0sGg92QNIMTpC9EGD4,10126
|
|
1002
1002
|
supervisely/nn/tracker/visualize.py,sha256=DY2cnRm4w6_e47xVuF9fwSnOP27ZWTRfv4MFPCyxsD4,20146
|
|
1003
1003
|
supervisely/nn/tracker/botsort/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
1004
1004
|
supervisely/nn/tracker/botsort/botsort_config.yaml,sha256=q_7Gp1-15lGYOLv7JvxVJ69mm6hbCLbUAl_ZBOYNGpw,535
|
|
@@ -1096,7 +1096,7 @@ supervisely/video_annotation/frame.py,sha256=np21FqavJ3xW9VbLbohifDwZQtF5dWIsNSG
|
|
|
1096
1096
|
supervisely/video_annotation/frame_collection.py,sha256=YYA8NMywLwpzeqVZuifhwlW5gAeQr9NLOANMT4jWpyg,15037
|
|
1097
1097
|
supervisely/video_annotation/key_id_map.py,sha256=KayYOhTtAe3ITq1-NQ82T6YIiBjmu4aJm8t4UxdvI8U,37712
|
|
1098
1098
|
supervisely/video_annotation/video_annotation.py,sha256=WsZws8ls6Og3eXQJlEp9PT5DOceMnhajr82KL-8rd6c,28901
|
|
1099
|
-
supervisely/video_annotation/video_figure.py,sha256=
|
|
1099
|
+
supervisely/video_annotation/video_figure.py,sha256=r_tcVoiWWIfCa_8vmF1wPI7qlE1QQgpOqL1XQnAAqiM,25404
|
|
1100
1100
|
supervisely/video_annotation/video_object.py,sha256=LnJg-tvvjfU_m-GfRp71PUziOXJVBEfoTro2P9EhjIs,16759
|
|
1101
1101
|
supervisely/video_annotation/video_object_collection.py,sha256=vY-n7yJ5Fn6-1OiXpS65uY4_VD_VRMQL7isgSbtugFw,9108
|
|
1102
1102
|
supervisely/video_annotation/video_tag.py,sha256=cF6EoZ7lxcVacnvtVpSW7A7nbkCp8AYkRjtMCD_wqo8,18312
|
|
@@ -1127,9 +1127,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
1127
1127
|
supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
|
|
1128
1128
|
supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
|
|
1129
1129
|
supervisely_lib/__init__.py,sha256=yRwzEQmVwSd6lUQoAUdBngKEOlnoQ6hA9ZcoZGJRNC4,331
|
|
1130
|
-
supervisely-6.73.
|
|
1131
|
-
supervisely-6.73.
|
|
1132
|
-
supervisely-6.73.
|
|
1133
|
-
supervisely-6.73.
|
|
1134
|
-
supervisely-6.73.
|
|
1135
|
-
supervisely-6.73.
|
|
1130
|
+
supervisely-6.73.441.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
1131
|
+
supervisely-6.73.441.dist-info/METADATA,sha256=uhVLj_ydUAqj4wTu-LxNrR_oto1sTrPETKyV7viy49I,35480
|
|
1132
|
+
supervisely-6.73.441.dist-info/WHEEL,sha256=iAkIy5fosb7FzIOwONchHf19Qu7_1wCWyFNR5gu9nU0,91
|
|
1133
|
+
supervisely-6.73.441.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
|
|
1134
|
+
supervisely-6.73.441.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
|
|
1135
|
+
supervisely-6.73.441.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|