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

@@ -2,6 +2,7 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  import json
5
+ import time
5
6
  from dataclasses import dataclass
6
7
  from time import sleep
7
8
  from typing import Any, Dict, List, NamedTuple, Optional, Union
@@ -536,10 +537,7 @@ class AppApi(TaskApi):
536
537
  self._enabled = True
537
538
  if is_development():
538
539
  self._enabled = False
539
- logger.warning(
540
- "Workflow is disabled in development mode. "
541
- "To enable it, use `api.app.workflow.enable()` right after Api initialization."
542
- )
540
+ self.__last_warning_time = None
543
541
 
544
542
  def enable(self):
545
543
  """Enable the workflow functionality."""
@@ -574,10 +572,18 @@ class AppApi(TaskApi):
574
572
  if min_instance_version is not None
575
573
  else self._min_instance_version
576
574
  )
577
- if (
578
- not check_workflow_compatibility(self._api, version_to_check)
579
- or not self._enabled
580
- ):
575
+ if not self.is_enabled():
576
+ if (
577
+ self.__last_warning_time is None
578
+ or time.monotonic() - self.__last_warning_time > 60
579
+ ):
580
+ self.__last_warning_time = time.monotonic()
581
+ logger.warning(
582
+ "Workflow is disabled in development mode. "
583
+ "To enable it, use `api.app.workflow.enable()` right after Api initialization."
584
+ )
585
+ return
586
+ if not check_workflow_compatibility(self._api, version_to_check):
581
587
  logger.info(f"Workflow method `{func.__name__}` is disabled.")
582
588
  return
583
589
  return func(self, *args, **kwargs)
@@ -574,10 +574,15 @@ class Inference:
574
574
  for prediction in predictions:
575
575
  if (
576
576
  not classes_whitelist in (None, "all")
577
+ and hasattr(prediction, "class_name")
577
578
  and prediction.class_name not in classes_whitelist
578
579
  ):
579
580
  continue
580
- label = self._create_label(prediction)
581
+ if "classes_whitelist" in inspect.signature(self._create_label).parameters:
582
+ # pylint: disable=unexpected-keyword-arg
583
+ label = self._create_label(prediction, classes_whitelist) # pylint: disable=too-many-function-args
584
+ else:
585
+ label = self._create_label(prediction)
581
586
  if label is None:
582
587
  # for example empty mask
583
588
  continue
@@ -2543,17 +2548,52 @@ def clean_up_cuda():
2543
2548
  logger.debug("Error in clean_up_cuda.", exc_info=True)
2544
2549
 
2545
2550
 
2551
+ def _fix_classes_names(meta: ProjectMeta, ann: Annotation):
2552
+ def _replace_strip(s, chars: str, replacement: str = "_") -> str:
2553
+ replace_pattern = f"^[{re.escape(chars)}]+|[{re.escape(chars)}]+$"
2554
+ return re.sub(replace_pattern, replacement, s)
2555
+
2556
+ replaced_classes_in_meta = []
2557
+ for obj_class in meta.obj_classes:
2558
+ obj_class_name = _replace_strip(obj_class.name, " ", "")
2559
+ if obj_class_name != obj_class.name:
2560
+ new_obj_class = obj_class.clone(name=obj_class_name)
2561
+ meta = meta.delete_obj_class(obj_class.name)
2562
+ meta = meta.add_obj_class(new_obj_class)
2563
+ replaced_classes_in_meta.append((obj_class.name, obj_class_name))
2564
+ replaced_classes_in_ann = set()
2565
+ new_labels = []
2566
+ for label in ann.labels:
2567
+ obj_class = label.obj_class
2568
+ obj_class_name = _replace_strip(obj_class.name, " ", "")
2569
+ if obj_class_name != obj_class.name:
2570
+ new_obj_class = obj_class.clone(name=obj_class_name)
2571
+ label = label.clone(obj_class=new_obj_class)
2572
+ replaced_classes_in_ann.add((obj_class.name, obj_class_name))
2573
+ new_labels.append(label)
2574
+ ann = ann.clone(labels=new_labels)
2575
+ return meta, ann, replaced_classes_in_meta, list(replaced_classes_in_ann)
2576
+
2577
+
2546
2578
  def update_meta_and_ann(meta: ProjectMeta, ann: Annotation):
2547
2579
  """Update project meta and annotation to match each other
2548
2580
  If obj class or tag meta from annotation conflicts with project meta
2549
2581
  add suffix to obj class or tag meta.
2550
2582
  Return tuple of updated project meta, annotation and boolean flag if meta was changed."""
2551
- obj_classes_suffixes = {"_nn"}
2552
- tag_meta_suffixes = {"_nn"}
2583
+ obj_classes_suffixes = ["_nn"]
2584
+ tag_meta_suffixes = ["_nn"]
2553
2585
  ann_obj_classes = {}
2554
2586
  ann_tag_metas = {}
2555
2587
  meta_changed = False
2556
2588
 
2589
+ meta, ann, replaced_classes_in_meta, replaced_classes_in_ann = _fix_classes_names(meta, ann)
2590
+ if replaced_classes_in_meta:
2591
+ meta_changed = True
2592
+ logger.warning(
2593
+ "Some classes names were fixed in project meta",
2594
+ extra={"replaced_classes": {old: new for old, new in replaced_classes_in_meta}},
2595
+ )
2596
+
2557
2597
  # get all obj classes and tag metas from annotation
2558
2598
  for label in ann.labels:
2559
2599
  ann_obj_classes[label.obj_class.name] = label.obj_class
@@ -2563,7 +2603,8 @@ def update_meta_and_ann(meta: ProjectMeta, ann: Annotation):
2563
2603
  ann_tag_metas[tag.meta.name] = tag.meta
2564
2604
 
2565
2605
  # check if obj classes are in project meta
2566
- # if not, add them with suffix
2606
+ # if not, add them.
2607
+ # if shape is different, add them with suffix
2567
2608
  changed_obj_classes = {}
2568
2609
  for ann_obj_class in ann_obj_classes.values():
2569
2610
  if meta.get_obj_class(ann_obj_class.name) is None:
@@ -3,9 +3,11 @@ from typing import Any, Dict, List
3
3
  import numpy as np
4
4
 
5
5
  from supervisely.annotation.label import Label
6
+ from supervisely.annotation.obj_class import ObjClass
6
7
  from supervisely.geometry.bitmap import Bitmap
7
8
  from supervisely.nn.inference.inference import Inference
8
9
  from supervisely.nn.prediction_dto import PredictionSegmentation
10
+ from supervisely.project.project_meta import ProjectMeta
9
11
  from supervisely.sly_logger import logger
10
12
 
11
13
 
@@ -24,20 +26,48 @@ class SemanticSegmentation(Inference):
24
26
  def _get_obj_class_shape(self):
25
27
  return Bitmap
26
28
 
27
- def _create_label(self, dto: PredictionSegmentation):
28
- image_classes = np.unique(dto.mask)
29
+ def _find_bg_class_index(self, class_names: List[str]):
30
+ possible_bg_names = ["background", "bg", "unlabeled", "neutral", "__bg__"]
31
+ bg_class_index = None
32
+ for i, name in enumerate(class_names):
33
+ if name in possible_bg_names:
34
+ bg_class_index = i
35
+ break
36
+ return bg_class_index
37
+
38
+ def _add_default_bg_class(self, meta: ProjectMeta):
39
+ default_bg_class_name = "__bg__"
40
+ obj_class = meta.get_obj_class(default_bg_class_name)
41
+ if obj_class is None:
42
+ obj_class = ObjClass(default_bg_class_name, self._get_obj_class_shape())
43
+ meta = meta.add_obj_class(obj_class)
44
+ return meta, obj_class
45
+
46
+ def _get_or_create_bg_obj_class(self, classes):
47
+ bg_class_index = self._find_bg_class_index(classes)
48
+ if bg_class_index is None:
49
+ self._model_meta, bg_obj_class = self._add_default_bg_class(self.model_meta)
50
+ else:
51
+ bg_class_name = classes[bg_class_index]
52
+ bg_obj_class = self.model_meta.get_obj_class(bg_class_name)
53
+ return bg_obj_class
54
+
55
+ def _create_label(self, dto: PredictionSegmentation, classes_whitelist: List[str] = None):
56
+ classes = self.get_classes()
57
+
58
+ image_classes_indexes = np.unique(dto.mask)
29
59
  labels = []
30
- for class_idx in image_classes:
60
+ for class_idx in image_classes_indexes:
31
61
  class_mask = dto.mask == class_idx
32
- class_name = self.get_classes()[class_idx]
33
- obj_class = self.model_meta.get_obj_class(class_name)
62
+ class_name = classes[class_idx]
63
+ if classes_whitelist not in (None, "all") and class_name not in classes_whitelist:
64
+ obj_class = self._get_or_create_bg_obj_class(classes)
65
+ else:
66
+ obj_class = self.model_meta.get_obj_class(class_name)
34
67
  if obj_class is None:
35
68
  raise KeyError(
36
69
  f"Class {class_name} not found in model classes {self.get_classes()}"
37
70
  )
38
- if not class_mask.any(): # skip empty masks
39
- logger.debug(f"Mask of class {class_name} is empty and will be sklipped")
40
- return None
41
71
  geometry = Bitmap(class_mask, extra_validation=False)
42
72
  label = Label(geometry, obj_class)
43
73
  labels.append(label)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: supervisely
3
- Version: 6.73.225
3
+ Version: 6.73.226
4
4
  Summary: Supervisely Python SDK.
5
5
  Home-page: https://github.com/supervisely/supervisely
6
6
  Author: Supervisely
@@ -23,7 +23,7 @@ supervisely/api/advanced_api.py,sha256=Nd5cCnHFWc3PSUrCtENxTGtDjS37_lCHXsgXvUI3T
23
23
  supervisely/api/agent_api.py,sha256=ShWAIlXcWXcyI9fqVuP5GZVCigCMJmjnvdGUfLspD6Y,8890
24
24
  supervisely/api/annotation_api.py,sha256=Eps-Jf10_SQFy7DjghUnyiM6DcVJBsamHDViRAXv2fg,51403
25
25
  supervisely/api/api.py,sha256=Jvc0nQqu6q4-1ey26AJiCcw96BzqP0ORBQqsoKO7gOI,60633
26
- supervisely/api/app_api.py,sha256=zX3Iy16RuGwtcLZfMs3YfUFc93S9AVGb3W_eINeMjOs,66729
26
+ supervisely/api/app_api.py,sha256=hjoL24Nc1POlIqz5bkpMBij5D-cwCHvkznkaGpODyzA,67086
27
27
  supervisely/api/dataset_api.py,sha256=7iwAyz3pmzFG2i072gLdXjczfBGbyj-V_rRl7Tx-V30,37944
28
28
  supervisely/api/file_api.py,sha256=UQM5susk1DMgmEEZZq4tiMCKbglKYl8MqiZn1iPLqus,76821
29
29
  supervisely/api/github_api.py,sha256=NIexNjEer9H5rf5sw2LEZd7C1WR-tK4t6IZzsgeAAwQ,623
@@ -817,7 +817,7 @@ supervisely/nn/benchmark/visualization/widgets/table/__init__.py,sha256=47DEQpj8
817
817
  supervisely/nn/benchmark/visualization/widgets/table/table.py,sha256=YiCpt-mdINJnNBWsUTPkRR_9w09Ne2Y0n93DY8vsE8I,4090
818
818
  supervisely/nn/inference/__init__.py,sha256=mtEci4Puu-fRXDnGn8RP47o97rv3VTE0hjbYO34Zwqg,1622
819
819
  supervisely/nn/inference/cache.py,sha256=WylgHgPQRIoA_RDks8FyKgHqeZZ_YFoyddxkVvOX2YQ,25713
820
- supervisely/nn/inference/inference.py,sha256=pwTh6_EQ-sJNXTBD08eUMdOH8VoNF2uJUTr_P1-BuN0,114983
820
+ supervisely/nn/inference/inference.py,sha256=jqhugSdwrKPyimiSxGvsJYLTjAyrxVmOl2FNql6f4aA,116982
821
821
  supervisely/nn/inference/session.py,sha256=jmkkxbe2kH-lEgUU6Afh62jP68dxfhF5v6OGDfLU62E,35757
822
822
  supervisely/nn/inference/video_inference.py,sha256=8Bshjr6rDyLay5Za8IB8Dr6FURMO2R_v7aELasO8pR4,5746
823
823
  supervisely/nn/inference/gui/__init__.py,sha256=e3RKi93bI1r_0Dkvs_gaR1p_jkzkBMNjrcx-RVlm93k,88
@@ -846,7 +846,7 @@ supervisely/nn/inference/promptable_segmentation/promptable_segmentation.py,sha2
846
846
  supervisely/nn/inference/salient_object_segmentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
847
847
  supervisely/nn/inference/salient_object_segmentation/salient_object_segmentation.py,sha256=fbTcI2GNXLD7JzFos05XqFDQCa57csaoYQFakYJRZh8,8136
848
848
  supervisely/nn/inference/semantic_segmentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
849
- supervisely/nn/inference/semantic_segmentation/semantic_segmentation.py,sha256=e4n523yGOGcZNIZI3bSHL0TgDjuttLf2r0piaakyGuA,2059
849
+ supervisely/nn/inference/semantic_segmentation/semantic_segmentation.py,sha256=xpmViSYm1v_ZxlYyqiD_DiB7_LEynv9ZoU0t2QHEx8A,3370
850
850
  supervisely/nn/inference/tracking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
851
851
  supervisely/nn/inference/tracking/bbox_tracking.py,sha256=URWGoYrCRN3yC4MyLx2_eZziZYwX6mPA8OLJqUOsAgA,15307
852
852
  supervisely/nn/inference/tracking/functional.py,sha256=LpVu2gvOOpr9D_uvwTPZey1wUCAhV-E20RPKmCSIrK4,1774
@@ -997,9 +997,9 @@ supervisely/worker_proto/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
997
997
  supervisely/worker_proto/worker_api_pb2.py,sha256=VQfi5JRBHs2pFCK1snec3JECgGnua3Xjqw_-b3aFxuM,59142
998
998
  supervisely/worker_proto/worker_api_pb2_grpc.py,sha256=3BwQXOaP9qpdi0Dt9EKG--Lm8KGN0C5AgmUfRv77_Jk,28940
999
999
  supervisely_lib/__init__.py,sha256=7-3QnN8Zf0wj8NCr2oJmqoQWMKKPKTECvjH9pd2S5vY,159
1000
- supervisely-6.73.225.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
- supervisely-6.73.225.dist-info/METADATA,sha256=oS0A-4lJ3n2xZcXc0n7SEXjpkQjY3e0WC5OMYDa4lRk,33150
1002
- supervisely-6.73.225.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
- supervisely-6.73.225.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
- supervisely-6.73.225.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
- supervisely-6.73.225.dist-info/RECORD,,
1000
+ supervisely-6.73.226.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
1001
+ supervisely-6.73.226.dist-info/METADATA,sha256=MFZ1QnRu-QzhumIcVsb7aQvcfXiXxcbQ_dX9mrVG1tk,33150
1002
+ supervisely-6.73.226.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
1003
+ supervisely-6.73.226.dist-info/entry_points.txt,sha256=U96-5Hxrp2ApRjnCoUiUhWMqijqh8zLR03sEhWtAcms,102
1004
+ supervisely-6.73.226.dist-info/top_level.txt,sha256=kcFVwb7SXtfqZifrZaSE3owHExX4gcNYe7Q2uoby084,28
1005
+ supervisely-6.73.226.dist-info/RECORD,,