Source code for supervisely.annotation.label

# coding: utf-8
"""Labeling object for :class:`Annotation<supervisely.annotation.annotation.Annotation>`"""

# docs
from __future__ import annotations

from typing import Dict, List, Optional, Tuple, Union

import numpy as np
from PIL.ImageFont import FreeTypeFont

from supervisely._utils import take_with_default
from supervisely.annotation.json_geometries_map import GET_GEOMETRY_FROM_STR
from supervisely.annotation.obj_class import ObjClass
from supervisely.annotation.tag import Tag
from supervisely.annotation.tag_collection import TagCollection
from supervisely.geometry.any_geometry import AnyGeometry
from supervisely.geometry.constants import GEOMETRY_SHAPE, GEOMETRY_TYPE
from supervisely.geometry.geometry import Geometry
from supervisely.geometry.image_rotator import ImageRotator
from supervisely.geometry.multichannel_bitmap import MultichannelBitmap
from supervisely.geometry.rectangle import Rectangle
from supervisely.imaging import font as sly_font
from supervisely.imaging import image as sly_image
from supervisely.project.project_meta import ProjectMeta


[docs]class LabelJsonFields: """Json fields for :class:`Annotation<supervisely.annotation.label.Label>`""" OBJ_CLASS_NAME = "classTitle" """""" OBJ_CLASS_ID = "classId" """""" DESCRIPTION = "description" """""" TAGS = "tags" """""" INSTANCE_KEY = "instance" """"""
class LabelBase: """ Labeling object for :class:`Annotation<supervisely.annotation.annotation.Annotation>`. :class:`Label<Label>` object is immutable. :param geometry: Label :class:`geometry<supervisely.geometry.geometry.Geometry>`. :type geometry: Geometry :param obj_class: Label :class:`class<supervisely.annotation.obj_class.ObjClass>`. :type obj_class: ObjClass :param tags: Label :class:`tags<supervisely.annotation.tag_collection.TagCollection>`. :type tags: TagCollection or List[Tag] :param description: Label description. :type description: str, optional :Usage example: .. code-block:: python import supervisely as sly # Simple Label example class_kiwi = sly.ObjClass('kiwi', sly.Rectangle) figure = sly.Rectangle(0, 0, 300, 300) label_kiwi = sly.Label(figure, class_kiwi) # More complex Label example # Tag meta_kiwi = sly.TagMeta('kiwi_tag', sly.TagValueType.ANY_STRING) tag_kiwi = sly.Tag(meta_kiwi, 'Hello') # ObjClass class_kiwi = sly.ObjClass('kiwi', sly.Rectangle) # Label geometry_figure = sly.Rectangle(0, 0, 300, 300) label = sly.Label(figure, class_kiwi, sly.TagCollection([tag_kiwi]), 'Label description') # or sly.Label(figure, class_kiwi, [tag_kiwi], 'Label description') """ def __init__( self, geometry: Geometry, obj_class: ObjClass, tags: Optional[Union[TagCollection, List[Tag]]] = None, description: Optional[str] = "", binding_key=None, ): self._geometry = geometry self._obj_class = obj_class self._tags = take_with_default(tags, TagCollection()) self._description = description self._validate_geometry_type() self._validate_geometry() if not isinstance(tags, TagCollection): self._tags = TagCollection(tags) self._binding_key = binding_key def _validate_geometry(self): """ The function checks the name of the Object for compliance. :return: generate ValueError error if name is mismatch """ self._geometry.validate( self._obj_class.geometry_type.geometry_name(), self.obj_class.geometry_config ) def _validate_geometry_type(self): raise NotImplementedError() @property def obj_class(self) -> ObjClass: """ ObjClass of the current Label. :return: ObjClass object :rtype: :class:`ObjClass<supervisely.annotation.obj_class.ObjClass>` :Usage example: .. code-block:: python class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(150, 150, 400, 500), class_dog) label_dog_json = label_dog.obj_class.to_json() print(label_dog_json) # Output: { # "title": "dog", # "shape": "rectangle", # "color": "#0F8A12", # "geometry_config": {}, # "hotkey": "" # } """ return self._obj_class @property def description(self) -> str: """ Description of the current Label. :return: Description :rtype: :class:`str` :Usage example: .. code-block:: python class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(150, 150, 400, 500), class_dog, description="Insert Label description here") print(label_dog.description) # Output: 'Insert Label description here' """ return self._description @property def geometry(self) -> Geometry: """ Geometry of the current Label. :return: Geometry object :rtype: :class:`Geometry<supervisely.geometry>` :Usage example: .. code-block:: python class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(150, 150, 400, 500), class_dog) label_json = label_dog.geometry.to_json() print(label_json) # Output: { # "points": { # "exterior": [ # [ # 150, # 150 # ], # [ # 500, # 400 # ] # ], # "interior": [] # } # } """ return self._geometry @property def tags(self) -> TagCollection: """ TagCollection of the current Label. :return: TagCollection object :rtype: :class:`TagCollection<supervisely.annotation.tag.TagCollection>` :Usage example: .. code-block:: python meta_dog = sly.TagMeta('dog', sly.TagValueType.ANY_STRING) tag_dog = sly.Tag(meta_dog, 'Woof') class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(100, 100, 700, 900), class_dog, sly.TagCollection([tag_dog])) label_dog_json = label_dog.tags.to_json() print(label_dog_json) # Output: [ # { # "name": "dog", # "value": "Woof" # } # ] """ return self._tags.clone() def to_json(self) -> Dict: """ Convert the Label to a json dict. Read more about `Supervisely format <https://docs.supervise.ly/data-organization/00_ann_format_navi>`_. :return: Json format as a dict :rtype: :class:`dict` :Usage example: .. code-block:: python import supervisely as sly meta_dog = sly.TagMeta('dog', sly.TagValueType.ANY_STRING) tag_dog = sly.Tag(meta_dog, 'Woof') class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(100, 100, 700, 900), class_dog, sly.TagCollection([tag_dog]), description='Insert Label description here') label_dog_json = label_dog.to_json() print(label_dog_json) # Output: { # "classTitle": "dog", # "description": "", # "tags": [ # { # "name": "dog", # "value": "Woof" # } # ], # "points": { # "exterior": [[100, 100],[900, 700]], # "interior": [] # }, # "geometryType": "rectangle", # "shape": "rectangle" # } """ res = { LabelJsonFields.OBJ_CLASS_NAME: self.obj_class.name, LabelJsonFields.DESCRIPTION: self.description, LabelJsonFields.TAGS: self.tags.to_json(), **self.geometry.to_json(), GEOMETRY_TYPE: self.geometry.geometry_name(), GEOMETRY_SHAPE: self.geometry.geometry_name(), } if self.obj_class.sly_id is not None: res[LabelJsonFields.OBJ_CLASS_ID] = self.obj_class.sly_id if self.binding_key is not None: res[LabelJsonFields.INSTANCE_KEY] = self.binding_key return res @classmethod def from_json(cls, data: Dict, project_meta: ProjectMeta) -> LabelBase: """ Convert a json dict to Label. Read more about `Supervisely format <https://docs.supervise.ly/data-organization/00_ann_format_navi>`_. :param data: Label in json format as a dict. :type data: dict :param project_meta: Input ProjectMeta. :type project_meta: ProjectMeta :return: Label object :rtype: :class:`Label<LabelBase>` :Usage example: .. code-block:: python import supervisely as sly address = 'https://app.supervise.ly/' token = 'Your Supervisely API Token' api = sly.Api(address, token) meta = api.project.get_meta(PROJECT_ID) data = { "classTitle": "dog", "tags": [ { "name": "dog", "value": "Woof" } ], "points": { "exterior": [[100, 100], [900, 700]], "interior": [] } } label_dog = sly.Label.from_json(data, meta) """ obj_class_name = data[LabelJsonFields.OBJ_CLASS_NAME] obj_class = project_meta.get_obj_class(obj_class_name) if obj_class is None: raise RuntimeError( f"Failed to deserialize a Label object from JSON: " f"label class name {obj_class_name} was not found in the given project meta." ) if obj_class.geometry_type is AnyGeometry: geometry_type_actual = GET_GEOMETRY_FROM_STR( data[GEOMETRY_TYPE] if GEOMETRY_TYPE in data else data[GEOMETRY_SHAPE] ) geometry = geometry_type_actual.from_json(data) else: geometry = obj_class.geometry_type.from_json(data) binding_key = data.get(LabelJsonFields.INSTANCE_KEY) return cls( geometry=geometry, obj_class=obj_class, tags=TagCollection.from_json(data[LabelJsonFields.TAGS], project_meta.tag_metas), description=data.get(LabelJsonFields.DESCRIPTION, ""), binding_key=binding_key, ) def add_tag(self, tag: Tag) -> LabelBase: """ Adds Tag to the current Label. :param tag: Tag to be added. :type tag: Tag :return: Label object :rtype: :class:`Label<LabelBase>` :Usage example: .. code-block:: python import supervisely as sly # Create label class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(0, 0, 500, 600), class_dog) # Create tag meta_dog = sly.TagMeta('dog', sly.TagValueType.NONE) tag_dog = sly.Tag(meta_dog) # Add Tag # Remember that Label object is immutable, and we need to assign new instance of Label to a new variable new_label = label_dog.add_tag(tag_dog) """ return self.clone(tags=self._tags.add(tag)) def add_tags(self, tags: List[Tag]) -> LabelBase: """ Adds multiple Tags to the current Label. :param tags: List of Tags to be added. :type tags: List[Tag] :return: Label object :rtype: :class:`Label<LabelBase>` :Usage example: .. code-block:: python import supervisely as sly # Create label class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(0, 0, 500, 600), class_dog) # Create tags meta_dog = sly.TagMeta('dog', sly.TagValueType.NONE) tag_dog = sly.Tag(meta_dog) meta_cat = sly.TagMeta('cat', sly.TagValueType.NONE) tag_cat = sly.Tag(meta_cat) tags_arr = [tag_dog, tag_cat] # Add Tags # Remember that Label object is immutable, and we need to assign new instance of Label to a new variable new_label = label_dog.add_tags(tags_arr) """ return self.clone(tags=self._tags.add_items(tags)) def clone( self, geometry: Optional[Geometry] = None, obj_class: Optional[ObjClass] = None, tags: Optional[Union[TagCollection, List[Tag]]] = None, description: Optional[str] = None, binding_key: Optional[str] = None, ) -> LabelBase: """ Makes a copy of Label with new fields, if fields are given, otherwise it will use fields of the original Label. :param geometry: Label :class:`geometry<supervisely.geometry.geometry.Geometry>`. :type geometry: Geometry :param obj_class: Label :class:`class<supervisely.annotation.obj_class.ObjClass>`. :type obj_class: ObjClass :param tags: Label :class:`tags<supervisely.annotation.tag.TagCollection>`. :type tags: TagCollection or List[Tag] :param description: Label description. :type description: str, optional :return: New instance of Label :rtype: :class:`Label<LabelBase>` :Usage example: .. code-block:: python import supervisely as sly import numpy as np # Original Label class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(150, 150, 500, 400), class_dog) # Let's clone our Label, but with different Geometry coordinates # Remember that Label object is immutable, and we need to assign new instance of Label to a new variable clone_label_dog = label_dog.clone(sly.Rectangle(100, 100, 500, 500), class_dog) # Let's clone our Label with new TagCollection and description meta_breed = sly.TagMeta('breed', sly.TagValueType.ANY_STRING) tag_breed = sly.Tag(meta_breed, 'German Shepherd') tags = sly.TagCollection([tag_breed]) # Remember that Label object is immutable, and we need to assign new instance of Label to a new variable clone_label_dog_2 = label_dog.clone(tags=tags, description='Dog breed german shepherd') # Note that you can't clone Label if ObjClass geometry type differ from the new given geometry mask = np.array([[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]], dtype=np.uint8) mask_bool = mask==1 clone_label_dog = label_dog.clone(sly.Label(sly.Bitmap(mask_bool), class_dog)) # In this case RuntimeError will be raised """ return self.__class__( geometry=take_with_default(geometry, self.geometry), obj_class=take_with_default(obj_class, self.obj_class), tags=take_with_default(tags, self.tags), description=take_with_default(description, self.description), binding_key=take_with_default(binding_key, self.binding_key), ) def crop(self, rect: Rectangle) -> List[LabelBase]: """ Clones the current Label and crops it. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.crop_labels>`. :param rect: Rectangle object. :type rect: Rectangle :return: List of Labels with new geometries :rtype: :class:`List[Label]<LabelBase>` """ if rect.contains(self.geometry.to_bbox()): return [self] else: # for compatibility of old slightly invalid annotations, some of them may be out of image bounds. # will correct it automatically result_geometries = self.geometry.crop(rect) if len(result_geometries) == 1: result_geometries[0]._copy_creation_info_inplace(self.geometry) return [self.clone(geometry=result_geometries[0])] else: return [self.clone(geometry=g) for g in self.geometry.crop(rect)] def relative_crop(self, rect: Rectangle) -> List[LabelBase]: """ Clones the current Label and crops it, but return results with coordinates relative to the given Rectangle. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.relative_crop>`. :param rect: Rectangle object. :type rect: Rectangle :return: List of Labels with new geometries :rtype: :class:`List[Label]<LabelBase>` """ return [self.clone(geometry=g) for g in self.geometry.relative_crop(rect)] def rotate(self, rotator: ImageRotator) -> LabelBase: """ Clones the current Label and rotates it. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.rotate>`. :param rotator: ImageRotator object. :type rotator: ImageRotator :return: New instance of Label with rotated geometry :rtype: :class:`Label<LabelBase>` """ return self.clone(geometry=self.geometry.rotate(rotator)) def resize(self, in_size: Tuple[int, int], out_size: Tuple[int, int]) -> LabelBase: """ Clones the current Label and resizes it. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.resize>`. :param in_size: Input image size (height, width) of the Annotation to which Label belongs. :type in_size: Tuple[int, int] :param out_size: Desired output image size (height, width) of the Annotation to which Label belongs. :type out_size: Tuple[int, int] :return: New instance of Label with resized geometry :rtype: :class:`Label<LabelBase>` """ return self.clone(geometry=self.geometry.resize(in_size, out_size)) def scale(self, factor: float) -> LabelBase: """ Clones the current Label and scales it. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.scale>`. :param factor: Scale factor. :type factor: float :return: New instance of Label with scaled geometry :rtype: :class:`Label<LabelBase>` """ return self.clone(geometry=self.geometry.scale(factor)) def translate(self, drow: int, dcol: int) -> LabelBase: """ Clones the current Label and shifts it by a certain number of pixels. Mostly used for internal implementation. :param drow: Horizontal shift. :type drow: int :param dcol: Vertical shift. :type dcol: int :return: New instance of Label with translated geometry :rtype: :class:`Label<LabelBase>` :Usage example: .. code-block:: python import supervisely as sly address = 'https://app.supervise.ly/' token = 'Your Supervisely API Token' api = sly.Api(address, token) # Get image and annotation from API project_id = 117139 image_id = 194190568 meta_json = api.project.get_meta(project_id) meta = sly.ProjectMeta.from_json(meta_json) ann_info = api.annotation.download(image_id) ann = sly.Annotation.from_json(ann_info.annotation, meta) img = api.image.download_np(image_id) new_img = copy.deepcopy(img) ann.draw_pretty(img, thickness=3) # before # Translate label with name 'lemon' new_labels = [] for label in ann.labels: if label.obj_class.name == 'lemon': translate_label = label.translate(250, -350) new_labels.append(translate_label) else: new_labels.append(label) ann = ann.clone(labels=new_labels) ann.draw_pretty(new_img, thickness=3) # after """ return self.clone(geometry=self.geometry.translate(drow=drow, dcol=dcol)) def fliplr(self, img_size: Tuple[int, int]) -> LabelBase: """ Clones the current Label and flips it horizontally. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.fliplr>`. :param img_size: Input image size (height, width) of the Annotation to which Label belongs. :type img_size: Tuple[int, int] :return: New instance of Label with flipped geometry :rtype: :class:`Label<LabelBase>` """ return self.clone(geometry=self.geometry.fliplr(img_size)) def flipud(self, img_size: Tuple[int, int]) -> LabelBase: """ Clones the current Label and flips it vertically. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.flipud>`. :param img_size: Input image size (height, width) of the Annotation to which Label belongs. :type img_size: Tuple[int, int] :return: New instance of Label with flipped geometry :rtype: :class:`Label<LabelBase>` """ return self.clone(geometry=self.geometry.flipud(img_size)) def _get_font(self, img_size): """ The function get size of font for image with given size :return: font for drawing """ return sly_font.get_font(font_size=sly_font.get_readable_font_size(img_size)) def _draw_tags(self, bitmap, font, add_class_name=False): bbox = self.geometry.to_bbox() texts = [t.get_compact_str() for t in self.tags] texts = texts if add_class_name is False else [self.obj_class.name] + texts sly_image.draw_text_sequence( bitmap=bitmap, texts=texts, anchor_point=(bbox.top, bbox.left), corner_snap=sly_image.CornerAnchorMode.BOTTOM_LEFT, font=font, ) def _draw_class_name(self, bitmap, font): bbox = self.geometry.to_bbox() sly_image.draw_text( bitmap, self.obj_class.name, (bbox.top, bbox.left), corner_snap=sly_image.CornerAnchorMode.BOTTOM_LEFT, font=font, ) def draw( self, bitmap: np.ndarray, color: Optional[List[int, int, int]] = None, thickness: Optional[int] = 1, draw_tags: Optional[bool] = False, tags_font: Optional[FreeTypeFont] = None, draw_class_name: Optional[bool] = False, class_name_font: Optional[FreeTypeFont] = None, ) -> None: """ Draws current Label on image. Modifies Mask. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.draw>`. :param bitmap: image. :type bitmap: np.ndarray :param color: Drawing color in :class:`[R, G, B]`. :type color: List[int, int, int], optional :param thickness: Thickness of the drawing figure. :type thickness: int, optional :param draw_tags: Determines whether to draw tags on bitmap or not. :type draw_tags: bool, optional :param tags_font: Font of tags to be drawn, uses `FreeTypeFont <https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.FreeTypeFont>`_ from `PIL <https://pillow.readthedocs.io/en/stable/index.html>`_. :type tags_font: FreeTypeFont, optional :param draw_class_name: Draw the class name on the bitmap. If the draw_tags parameter is set to True, the class name will use the same font as the tags_font. :type draw_class_name: bool, optional :param class_name_font: Font of class name to be drawn, uses `FreeTypeFont <https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.FreeTypeFont>`_ from `PIL <https://pillow.readthedocs.io/en/stable/index.html>`_. :type class_name_font: FreeTypeFont, optional :return: :class:`None<None>` :rtype: :class:`NoneType<NoneType>` """ effective_color = take_with_default(color, self.obj_class.color) self.geometry.draw( bitmap, effective_color, thickness, config=self.obj_class.geometry_config ) if draw_tags: if tags_font is None: tags_font = self._get_font(bitmap.shape[:2]) self._draw_tags(bitmap, tags_font, add_class_name=draw_class_name) elif draw_class_name: if class_name_font is None: class_name_font = self._get_font(bitmap.shape[:2]) self._draw_class_name(bitmap, class_name_font) def get_mask(self, img_size: Tuple[int, int]) -> np.ndarray: """Returns 2D boolean mask of the label. With shape as img_size (height, width) and filled with True values inside the label and False values outside. dtype = np.bool shape = img_size :param img_size: size of the image (height, width) :type img_size: Tuple[int, int] :return: 2D boolean mask of the Label :rtype: np.ndarray """ bitmap = np.zeros(img_size + (3,), dtype=np.uint8) self.draw(bitmap, thickness=-1, color=[255, 255, 255]) return np.any(bitmap != 0, axis=-1) def draw_contour( self, bitmap: np.ndarray, color: Optional[List[int, int, int]] = None, thickness: Optional[int] = 1, draw_tags: Optional[bool] = False, tags_font: Optional[FreeTypeFont] = None, draw_class_name: Optional[bool] = False, class_name_font: Optional[FreeTypeFont] = None, ) -> None: """ Draws Label geometry contour on the given image. Modifies mask. Mostly used for internal implementation. See usage example in :class:`Annotation<supervisely.annotation.annotation.Annotation.draw_contour>`. :param bitmap: image. :type bitmap: np.ndarray :param color: Drawing color in :class:`[R, G, B]`. :type color: List[int, int, int], optional :param thickness: Thickness of the drawn contour. :type thickness: int, optional :param draw_tags: Determines whether to draw tags on bitmap or not. :type draw_tags: bool, optional :param tags_font: Font of tags to be drawn, uses `FreeTypeFont <https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.FreeTypeFont>`_ from `PIL <https://pillow.readthedocs.io/en/stable/index.html>`_. :type tags_font: FreeTypeFont, optional :param draw_class_name: Draw the class name on the bitmap. If the draw_tags parameter is set to True, the class name will use the same font as the tags_font. :type draw_class_name: bool, optional :param class_name_font: Font of class name to be drawn, uses `FreeTypeFont <https://pillow.readthedocs.io/en/stable/reference/ImageFont.html#PIL.ImageFont.FreeTypeFont>`_ from `PIL <https://pillow.readthedocs.io/en/stable/index.html>`_. :type class_name_font: FreeTypeFont, optional :return: :class:`None<None>` :rtype: :class:`NoneType<NoneType>` """ effective_color = take_with_default(color, self.obj_class.color) self.geometry.draw_contour( bitmap, effective_color, thickness, config=self.obj_class.geometry_config ) if draw_tags: if tags_font is None: tags_font = self._get_font(bitmap.shape[:2]) self._draw_tags(bitmap, tags_font, add_class_name=draw_class_name) elif draw_class_name: if class_name_font is None: class_name_font = self._get_font(bitmap.shape[:2]) self._draw_class_name(bitmap, class_name_font) @property def area(self) -> float: """ Label area. :return: Area of current geometry in Label. :rtype: :class:`float` :Usage example: .. code-block:: python import supervisely as sly # Create label class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(0, 0, 500, 600), class_dog) figure_area = label_dog.area print(figure_area) # Output: 301101.0 """ return self.geometry.area def convert(self, new_obj_class: ObjClass) -> List[LabelBase]: """ Converts Label geometry to another geometry shape. :param new_obj_class: ObjClass with new geometry shape. :type new_obj_class: ObjClass :return: List of Labels with converted geometries :rtype: :class:`List[Label]<LabelBase>` :Usage example: .. code-block:: python import supervisely as sly # Create label class_dog = sly.ObjClass('dog', sly.Rectangle) label_dog = sly.Label(sly.Rectangle(0, 0, 500, 600), class_dog) print(label_dog.geometry.to_json()) # {'geometryType': 'rectangle'} label_cat = sly.ObjClass('cat', sly.Bitmap) convert_label = label_dog.convert(label_cat) for label_bitmap in convert_label: print(label_bitmap.geometry.to_json()) # Output: {'geometryType': 'bitmap'} """ labels = [] geometries = self.geometry.convert(new_obj_class.geometry_type) for g in geometries: labels.append(self.clone(geometry=g, obj_class=new_obj_class)) return labels @property def binding_key(self): return self._binding_key @binding_key.setter def binding_key(self, key: Union[str, None]): if key is not None and type(key) is not str: raise TypeError("Key has to be of type string or None") self._binding_key = key @property def labeler_login(self): return self.geometry.labeler_login
[docs]class Label(LabelBase): def _validate_geometry_type(self): """ Checks geometry type for correctness """ if self._obj_class.geometry_type != AnyGeometry: if type(self._geometry) is not self._obj_class.geometry_type: raise RuntimeError( "Input geometry type {!r} != geometry type of ObjClass {}".format( type(self._geometry), self._obj_class.geometry_type ) )
class PixelwiseScoresLabel(LabelBase): def _validate_geometry_type(self): if type(self._geometry) is not MultichannelBitmap: raise RuntimeError( "Input geometry type {!r} != geometry type of ObjClass {}".format( type(self._geometry), MultichannelBitmap ) )