supervisely 6.73.292__py3-none-any.whl → 6.73.294__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.

Potentially problematic release.


This version of supervisely might be problematic. Click here for more details.

@@ -9,16 +9,21 @@ import json
9
9
  from collections import defaultdict
10
10
  from copy import deepcopy
11
11
  from typing import Any, Callable, Dict, List, Literal, NamedTuple, Optional, Union
12
+ from uuid import uuid4
12
13
 
13
14
  from tqdm import tqdm
14
15
 
15
16
  from supervisely._utils import batched
16
17
  from supervisely.annotation.annotation import Annotation, AnnotationJsonFields
17
18
  from supervisely.annotation.label import Label, LabelJsonFields
19
+ from supervisely.annotation.tag import Tag
20
+ from supervisely.annotation.tag_meta import TagMeta, TagValueType
18
21
  from supervisely.api.module_api import ApiField, ModuleApi
19
22
  from supervisely.geometry.alpha_mask import AlphaMask
20
23
  from supervisely.geometry.constants import BITMAP
21
24
  from supervisely.project.project_meta import ProjectMeta
25
+ from supervisely.project.project_type import _LABEL_GROUP_TAG_NAME
26
+ from supervisely.sly_logger import logger
22
27
 
23
28
 
24
29
  class AnnotationInfo(NamedTuple):
@@ -1640,3 +1645,86 @@ class AnnotationApi(ModuleApi):
1640
1645
  progress_cb(len(batch))
1641
1646
  ordered_results = [id_to_ann[image_id] for image_id in image_ids]
1642
1647
  return ordered_results
1648
+
1649
+ def append_labels_group(
1650
+ self,
1651
+ dataset_id: int,
1652
+ image_ids: List[int],
1653
+ labels: List[Label],
1654
+ project_meta: Optional[ProjectMeta] = None,
1655
+ group_name: Optional[str] = None,
1656
+ ) -> None:
1657
+ """
1658
+ Append group of labels to corresponding multiview images.
1659
+ This method will automatically add a tech tag to the labels to group them together.
1660
+ Please note that grouped labels is supported only in images project with multiview setup.
1661
+
1662
+ :param dataset_id: Dataset ID in Supervisely.
1663
+ :type dataset_id: int
1664
+ :param image_ids: List of Images IDs in Supervisely.
1665
+ :type image_ids: List[int]
1666
+ :param labels: List of Labels in Supervisely.
1667
+ :type labels: List[Label]
1668
+ :param project_meta: Project meta. If not provided, will try to get it from the server.
1669
+ :type project_meta: ProjectMeta, optional
1670
+ :param group_name: Group name. Labels will be assigned by tag with this value.
1671
+ :type group_name: str, optional
1672
+ :return: :class:`None<None>`
1673
+ :rtype: :class:`NoneType<NoneType>`
1674
+ :raises ValueError: if number of images and labels are not the same
1675
+
1676
+ :Usage example:
1677
+
1678
+ .. code-block:: python
1679
+
1680
+ import supervisely as sly
1681
+
1682
+ os.environ['SERVER_ADDRESS'] = 'https://app.supervisely.com'
1683
+ os.environ['API_TOKEN'] = 'Your Supervisely API Token'
1684
+ api = sly.Api.from_env()
1685
+
1686
+ dataset_id = 123456
1687
+ paths = ['path/to/audi_01.png', 'path/to/audi_02.png']
1688
+ images_group_name = 'audi'
1689
+
1690
+ image_infos = api.image.upload_multiview_images(dataset_id, images_group_name, paths)
1691
+
1692
+ image_ids = [info.id for info in image_infos]
1693
+ labels = [label1, label2]
1694
+ labels_group_name = 'left_wheel'
1695
+
1696
+ # upload group of labels to corresponding multiview images
1697
+ api.annotation.append_labels_group(image_ids, labels, labels_group_name)
1698
+ """
1699
+
1700
+ if len(image_ids) != len(labels):
1701
+ raise ValueError(
1702
+ "Number of images and labels must be the same."
1703
+ "If specific image does not have label, pass None instead."
1704
+ )
1705
+
1706
+ if group_name is None:
1707
+ group_name = str(uuid4().hex)
1708
+
1709
+ if project_meta is None:
1710
+ logger.warning(
1711
+ "Project meta is not provided. Will try to get it from the server. "
1712
+ "It is recommended to provide project meta to avoid extra API requests."
1713
+ )
1714
+ dataset_info = self._api.dataset.get_info_by_id(dataset_id)
1715
+ if dataset_info is None:
1716
+ raise ValueError(f"Dataset with ID {dataset_id} not found")
1717
+
1718
+ project_id = dataset_info.project_id
1719
+ project_meta = ProjectMeta.from_json(self._api.project.get_meta(project_id))
1720
+
1721
+ tag_meta = TagMeta(_LABEL_GROUP_TAG_NAME, TagValueType.ANY_STRING)
1722
+ labels = [l.add_tag(Tag(tag_meta, group_name)) for l in labels if l is not None]
1723
+
1724
+ anns_json = self._api.annotation.download_json_batch(
1725
+ dataset_id=dataset_id, image_ids=image_ids, force_metadata_for_links=False
1726
+ )
1727
+ anns = [Annotation.from_json(ann_json, project_meta) for ann_json in anns_json]
1728
+ updated_anns = [ann.add_label(label) for ann, label in zip(anns, labels)]
1729
+
1730
+ self._api.annotation.upload_anns(image_ids, updated_anns)
@@ -391,6 +391,7 @@ class ImageApi(RemoveableBulkModuleApi):
391
391
  project_id: Optional[int] = None,
392
392
  only_labelled: Optional[bool] = False,
393
393
  fields: Optional[List[str]] = None,
394
+ recursive: Optional[bool] = False,
394
395
  ) -> List[ImageInfo]:
395
396
  """
396
397
  List of Images in the given :class:`Dataset<supervisely.project.project.Dataset>`.
@@ -415,6 +416,8 @@ class ImageApi(RemoveableBulkModuleApi):
415
416
  :type only_labelled: bool, optional
416
417
  :param fields: List of fields to return. If None, returns all fields.
417
418
  :type fields: List[str], optional
419
+ :param recursive: If True, returns all images from dataset recursively (including images in nested datasets).
420
+ :type recursive: bool, optional
418
421
  :return: Objects with image information from Supervisely.
419
422
  :rtype: :class:`List[ImageInfo]<ImageInfo>`
420
423
  :Usage example:
@@ -474,6 +477,7 @@ class ImageApi(RemoveableBulkModuleApi):
474
477
  ApiField.SORT: sort,
475
478
  ApiField.SORT_ORDER: sort_order,
476
479
  ApiField.FORCE_METADATA_FOR_LINKS: force_metadata_for_links,
480
+ ApiField.RECURSIVE: recursive,
477
481
  }
478
482
  if only_labelled:
479
483
  data[ApiField.FILTERS] = [
@@ -4537,7 +4541,7 @@ class ImageApi(RemoveableBulkModuleApi):
4537
4541
  loop = sly.utils.get_or_create_event_loop()
4538
4542
  images = loop.run_until_complete(api.image.get_list_async(123456, per_page=600))
4539
4543
  """
4540
-
4544
+
4541
4545
  method = "images.list"
4542
4546
  dataset_info = kwargs.get("dataset_info", None)
4543
4547
 
@@ -52,6 +52,7 @@ from supervisely.project.project_settings import (
52
52
  ProjectSettingsJsonFields,
53
53
  )
54
54
  from supervisely.project.project_type import (
55
+ _LABEL_GROUP_TAG_NAME,
55
56
  _METADATA_SYSTEM_KEY,
56
57
  _METADATA_TIMESTAMP_KEY,
57
58
  _METADATA_VALIDATION_SCHEMA_KEY,
@@ -430,7 +431,9 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
430
431
  """
431
432
 
432
433
  fields = [
433
- x for x in self.info_sequence() if x not in (ApiField.ITEMS_COUNT, ApiField.SETTINGS, ApiField.CREATED_BY_ID)
434
+ x
435
+ for x in self.info_sequence()
436
+ if x not in (ApiField.ITEMS_COUNT, ApiField.SETTINGS, ApiField.CREATED_BY_ID)
434
437
  ]
435
438
 
436
439
  info = super().get_info_by_name(parent_id, name, fields)
@@ -1795,7 +1798,9 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
1795
1798
  meta = meta.add_obj_classes(classes)
1796
1799
  self.update_meta(id, meta)
1797
1800
 
1798
- def _set_custom_grouping_settings(self, id: int, group_images: bool, tag_name: str, sync: bool):
1801
+ def _set_custom_grouping_settings(
1802
+ self, id: int, group_images: bool, tag_name: str, sync: bool, label_group_tag_name: str = None
1803
+ ) -> None:
1799
1804
  """Sets the project settings for custom grouping.
1800
1805
 
1801
1806
  :param id: Project ID to set custom grouping settings.
@@ -1806,9 +1811,15 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
1806
1811
  :type tag_name: str
1807
1812
  :param sync: if True images will have synchronized view and labeling
1808
1813
  :type sync: bool
1814
+ :param label_group_tag_name: Name of the tag. Labels will be grouped by this tag
1815
+ :type label_group_tag_name: str
1816
+ :raises ValueError: if tag value type is not 'any_string'
1817
+ :return: None
1818
+ :rtype: :class:`NoneType`
1809
1819
  """
1810
1820
  meta = ProjectMeta.from_json(self.get_meta(id, with_settings=True))
1811
1821
  existing_tag_meta = meta.get_tag_meta(tag_name)
1822
+ need_update = False
1812
1823
  if existing_tag_meta is not None:
1813
1824
  if existing_tag_meta.value_type != TagValueType.ANY_STRING:
1814
1825
  raise ValueError(
@@ -1817,8 +1828,23 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
1817
1828
  )
1818
1829
  else:
1819
1830
  new_tag_meta = TagMeta(tag_name, TagValueType.ANY_STRING)
1820
- project_meta = meta.add_tag_meta(new_tag_meta)
1821
- self.update_meta(id, project_meta)
1831
+ meta = meta.add_tag_meta(new_tag_meta)
1832
+ need_update = True
1833
+ if label_group_tag_name is not None:
1834
+ label_group_tag_meta = meta.get_tag_meta(label_group_tag_name)
1835
+ if label_group_tag_meta is not None:
1836
+ if label_group_tag_meta.value_type != TagValueType.ANY_STRING:
1837
+ raise ValueError(
1838
+ f"Tag '{label_group_tag_name}' should have value type 'any_string', "
1839
+ f"but got '{label_group_tag_meta.value_type}' value type."
1840
+ )
1841
+ else:
1842
+ label_group_tag_meta = TagMeta(label_group_tag_name, TagValueType.ANY_STRING)
1843
+ meta = meta.add_tag_meta(label_group_tag_meta)
1844
+ need_update = True
1845
+ if need_update:
1846
+ self.update_meta(id, meta)
1847
+
1822
1848
  self.images_grouping(id, enable=group_images, tag_name=tag_name, sync=sync)
1823
1849
 
1824
1850
  def set_multispectral_settings(self, project_id: int) -> None:
@@ -1885,6 +1911,7 @@ class ProjectApi(CloneableModuleApi, UpdateableModule, RemoveableModuleApi):
1885
1911
  group_images=True,
1886
1912
  tag_name=_MULTIVIEW_TAG_NAME,
1887
1913
  sync=False,
1914
+ label_group_tag_name=_LABEL_GROUP_TAG_NAME,
1888
1915
  )
1889
1916
 
1890
1917
  def remove_permanently(
@@ -14,6 +14,7 @@ class ProjectType(StrEnum):
14
14
  # Constants for multispectral and multiview projects.
15
15
  _MULTISPECTRAL_TAG_NAME = "multispectral"
16
16
  _MULTIVIEW_TAG_NAME = "multiview"
17
+ _LABEL_GROUP_TAG_NAME = "@label-group-id"
17
18
 
18
19
  _METADATA_SYSTEM_KEY = "sly_system"
19
20
  _METADATA_VALIDATION_SCHEMA_KEY = "validation_schema"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.292
3
+ Version: 6.73.294
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -21,14 +21,14 @@ supervisely/annotation/tag_meta_mapper.py,sha256=RWeTrxJ64syodyhXIRSH007bX6Hr3B4
21
21
  supervisely/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  supervisely/api/advanced_api.py,sha256=Nd5cCnHFWc3PSUrCtENxTGtDjS37_lCHXsgXvUI3Ti8,2054
23
23
  supervisely/api/agent_api.py,sha256=ShWAIlXcWXcyI9fqVuP5GZVCigCMJmjnvdGUfLspD6Y,8890
24
- supervisely/api/annotation_api.py,sha256=fVQJOg5SLcD_mRUmPaVsJIOVTGFhsabRXqve0LyUgrc,64743
24
+ supervisely/api/annotation_api.py,sha256=kuk4qwojTJxYr2iqAKbW-QhWw_DFc4TsjA2Wc2MEaqw,68449
25
25
  supervisely/api/api.py,sha256=YBE6yi682H5dy3BBQtESmfC9hKZcbHyYRPNGLRldgSU,66014
26
26
  supervisely/api/app_api.py,sha256=RsbVej8WxWVn9cNo5s3Fqd1symsCdsfOaKVBKEUapRY,71927
27
27
  supervisely/api/dataset_api.py,sha256=GH7prDRJKyJlTv_7_Y-RkTwJN7ED4EkXNqqmi3iIdI4,41352
28
28
  supervisely/api/file_api.py,sha256=v2FsD3oljwNPqcDgEJRe8Bu5k0PYKzVhqmRb5QFaHAQ,83422
29
29
  supervisely/api/github_api.py,sha256=NIexNjEer9H5rf5sw2LEZd7C1WR-tK4t6IZzsgeAAwQ,623
30
30
  supervisely/api/image_annotation_tool_api.py,sha256=YcUo78jRDBJYvIjrd-Y6FJAasLta54nnxhyaGyanovA,5237
31
- supervisely/api/image_api.py,sha256=oi8luorbCaqMzd88_sjKeQQsX4eYOGJ8DVEbmSM44bw,192139
31
+ supervisely/api/image_api.py,sha256=WIML_6N1qgOWBm3acexmGSWz4hAaSxlYmUtbytROaP8,192375
32
32
  supervisely/api/import_storage_api.py,sha256=BDCgmR0Hv6OoiRHLCVPKt3iDxSVlQp1WrnKhAK_Zl84,460
33
33
  supervisely/api/issues_api.py,sha256=BqDJXmNoTzwc3xe6_-mA7FDFC5QQ-ahGbXk_HmpkSeQ,17925
34
34
  supervisely/api/labeling_job_api.py,sha256=odnzZjp29yM16Gq-FYkv-OA4WFMNJCLFo4qSikW2A7c,56280
@@ -36,7 +36,7 @@ supervisely/api/module_api.py,sha256=x5C1KvTulm5yZ-s9Sa47T4u--QRG6ditj1GhcqocTeA
36
36
  supervisely/api/neural_network_api.py,sha256=ktPVRO4Jeulougio8F0mioJJHwRJcX250Djp1wBoQ9c,7620
37
37
  supervisely/api/object_class_api.py,sha256=-rQcKwhBw3iL9KNH9c1ROgoimgWM1ls6Wi_tb1R-MzY,7683
38
38
  supervisely/api/plugin_api.py,sha256=TlfrosdRuYG4NUxk92QiQoVaOdztFspPpygyVa3M3zk,5283
39
- supervisely/api/project_api.py,sha256=ZTRx7LXsPLjMuGq_PhugPgN-OsGMtTRxputH9EA9iZ0,78774
39
+ supervisely/api/project_api.py,sha256=pBhZlSL3IA0FeBoK8eyhFDh8pnW_X8mbmit4cAJQUoo,79951
40
40
  supervisely/api/project_class_api.py,sha256=5cyjdGPPb2tpttu5WmYoOxUNiDxqiojschkhZumF0KM,1426
41
41
  supervisely/api/remote_storage_api.py,sha256=qTuPhPsstgEjRm1g-ZInddik8BNC_38YvBBPvgmim6U,17790
42
42
  supervisely/api/report_api.py,sha256=Om7CGulUbQ4BuJ16eDtz7luLe0JQNqab-LoLpUXu7YE,7123
@@ -1012,7 +1012,7 @@ supervisely/project/pointcloud_project.py,sha256=Kx1Vaes-krwG3BiRRtHRLQxb9G5m5bT
1012
1012
  supervisely/project/project.py,sha256=pDKRPZZCwW79wlfDi4JK9rOZisO2vWRfiOD_j7AId5k,202403
1013
1013
  supervisely/project/project_meta.py,sha256=26s8IiHC5Pg8B1AQi6_CrsWteioJP2in00cRNe8QlW0,51423
1014
1014
  supervisely/project/project_settings.py,sha256=NLThzU_DCynOK6hkHhVdFyezwprn9UqlnrLDe_3qhkY,9347
1015
- supervisely/project/project_type.py,sha256=_3RqW2CnDBKFOvSIrQT1RJQaiHirs34_jiQS8CkwCpo,530
1015
+ supervisely/project/project_type.py,sha256=EZDJFRi4MmC_5epYexBgML5WMZsWdEVk_CjqDQy5m3c,572
1016
1016
  supervisely/project/readme_template.md,sha256=rGmSLRVUSGjvorjpzl0sZ7YA4sKfDexl95NFtMISj3I,9128
1017
1017
  supervisely/project/upload.py,sha256=AjgHYgVZwUE25ygC5pqvFjdAladbyB8T78mlet5Qpho,3750
1018
1018
  supervisely/project/video_project.py,sha256=8fJeicVWNMbek24PmNRBtbnFhvXsnxPg5dpNrL5VNW4,63739
@@ -1071,9 +1071,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
1071
1071
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
1072
1072
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
1073
1073
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1074
- supervisely-6.73.292.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1075
- supervisely-6.73.292.dist-info/METADATA,sha256=ZKWuHNkAWaRrj9VSUnHGAP1J0stiYcNzyl4VaKzkxI8,33573
1076
- supervisely-6.73.292.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1077
- supervisely-6.73.292.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1078
- supervisely-6.73.292.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1079
- supervisely-6.73.292.dist-info/RECORD,,
1074
+ supervisely-6.73.294.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1075
+ supervisely-6.73.294.dist-info/METADATA,sha256=tgjdB_FSwcOSyWj9_Mxkeije_FDbelZVyzWcy4vGTDo,33573
1076
+ supervisely-6.73.294.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1077
+ supervisely-6.73.294.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1078
+ supervisely-6.73.294.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1079
+ supervisely-6.73.294.dist-info/RECORD,,