Source code for tensorbay.label.label_mask

#!/usr/bin/env python3
#
# Copyright 2021 Graviti. Licensed under MIT License.
#

"""Mask related classes."""

from typing import Any, Callable, Dict, Optional, Type, TypeVar

from ..utility import FileMixin, RemoteFileMixin, ReprMixin
from .basic import AttributeType, SubcatalogBase
from .supports import AttributesMixin, IsTrackingMixin, MaskCategoriesMixin


[docs]class SemanticMaskSubcatalog(SubcatalogBase, MaskCategoriesMixin, AttributesMixin): """This class defines the subcatalog for semantic mask type of labels. Attributes: description: The description of the entire semantic mask subcatalog. categories: All the possible categories in the corresponding dataset stored in a :class:`~tensorbay.utility.name.NameList` with the category names as keys and the :class:`~tensorbay.label.supports.CategoryInfo` as values. category_delimiter: The delimiter in category values indicating parent-child relationship. attributes: All the possible attributes in the corresponding dataset stored in a :class:`~tensorbay.utility.name.NameList` with the attribute names as keys and the :class:`~tensorbay.label.attribute.AttributeInfo` as values. is_tracking: Whether the Subcatalog contains tracking information. Examples: *Initialization Method 1:* Init from ``SemanticMaskSubcatalog.loads()`` method. >>> catalog = { ... "SEMANTIC_MASK": { ... "categories": [ ... {'name': 'cat', "categoryId": 1}, ... {'name': 'dog', "categoryId": 2} ... ], ... "attributes": [{'name': 'occluded', 'type': 'boolean'}], ... } ... } >>> SemanticMaskSubcatalog.loads(catalog["SEMANTIC_MASK"]) SemanticMaskSubcatalog( (categories): NameList [...], (attributes): NameList [...] ) *Initialization Method 2:* Init an empty SemanticMaskSubcatalog and then add the attributes. >>> semantic_mask_subcatalog = SemanticMaskSubcatalog() >>> semantic_mask_subcatalog.add_category("cat", 1) >>> semantic_mask_subcatalog.add_category("dog", 2) >>> semantic_mask_subcatalog.add_attribute("occluded", type_="boolean") >>> semantic_mask_subcatalog SemanticMaskSubcatalog( (categories): NameList [...], (attributes): NameList [...] ) """
[docs]class InstanceMaskSubcatalog(SubcatalogBase, MaskCategoriesMixin, IsTrackingMixin, AttributesMixin): """This class defines the subcatalog for instance mask type of labels. Attributes: description: The description of the entire instance mask subcatalog. categories: All the possible categories in the corresponding dataset stored in a :class:`~tensorbay.utility.name.NameList` with the category names as keys and the :class:`~tensorbay.label.supports.CategoryInfo` as values. category_delimiter: The delimiter in category values indicating parent-child relationship. attributes: All the possible attributes in the corresponding dataset stored in a :class:`~tensorbay.utility.name.NameList` with the attribute names as keys and the :class:`~tensorbay.label.attribute.AttributeInfo` as values. is_tracking: Whether the Subcatalog contains tracking information. Examples: *Initialization Method 1:* Init from ``InstanceMaskSubcatalog.loads()`` method. >>> catalog = { ... "INSTANCE_MASK": { ... "categories": [ ... {'name': 'background', "categoryId": 0} ... ], ... "attributes": [{'name': 'occluded', 'type': 'boolean'}], ... } ... } >>> InstanceMaskSubcatalog.loads(catalog["INSTANCE_MASK"]) InstanceMaskSubcatalog( (is_tracking): False, (categories): NameList [...], (attributes): NameList [...] ) *Initialization Method 2:* Init an empty InstanceMaskSubcatalog and then add the attributes. >>> instance_mask_subcatalog = InstanceMaskSubcatalog() >>> instance_mask_subcatalog.add_category("background", 0) >>> instance_mask_subcatalog.add_attribute("occluded", type_="boolean") >>> instance_mask_subcatalog InstanceMaskSubcatalog( (categories): NameList [...], (attributes): NameList [...] ) """
[docs]class PanopticMaskSubcatalog(SubcatalogBase, MaskCategoriesMixin, AttributesMixin): """This class defines the subcatalog for panoptic mask type of labels. Attributes: description: The description of the entire panoptic mask subcatalog. categories: All the possible categories in the corresponding dataset stored in a :class:`~tensorbay.utility.name.NameList` with the category names as keys and the :class:`~tensorbay.label.supports.CategoryInfo` as values. category_delimiter: The delimiter in category values indicating parent-child relationship. attributes: All the possible attributes in the corresponding dataset stored in a :class:`~tensorbay.utility.name.NameList` with the attribute names as keys and the :class:`~tensorbay.label.attribute.AttributeInfo` as values. is_tracking: Whether the Subcatalog contains tracking information. Examples: *Initialization Method 1:* Init from ``PanopticMaskSubcatalog.loads()`` method. >>> catalog = { ... "PANOPTIC_MASK": { ... "categories": [ ... {'name': 'cat', "categoryId": 1}, ... {'name': 'dog', "categoryId": 2} ... ], ... "attributes": [{'name': 'occluded', 'type': 'boolean'}], ... } ... } >>> PanopticMaskSubcatalog.loads(catalog["PANOPTIC_MASK"]) PanopticMaskSubcatalog( (categories): NameList [...], (attributes): NameList [...] ) *Initialization Method 2:* Init an empty PanopticMaskSubcatalog and then add the attributes. >>> panoptic_mask_subcatalog = PanopticMaskSubcatalog() >>> panoptic_mask_subcatalog.add_category("cat", 1) >>> panoptic_mask_subcatalog.add_category("dog", 2) >>> panoptic_mask_subcatalog.add_attribute("occluded", type_="boolean") >>> panoptic_mask_subcatalog PanopticMaskSubcatalog( (categories): NameList [...], (attributes): NameList [...] ) """
[docs]class SemanticMaskBase(ReprMixin): """SemanticMaskBase is a base class for the semantic mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the category id, and the value is the corresponding attributes. """ _repr_attrs = ("all_attributes",) all_attributes: Dict[int, AttributeType]
[docs]class InstanceMaskBase(ReprMixin): """InstanceMaskBase is a base class for the instance mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the instance id, and the value is the corresponding attributes. """ _repr_attrs = ("all_attributes",) all_attributes: Dict[int, AttributeType]
[docs]class PanopticMaskBase(ReprMixin): """PanopticMaskBase is a base class for the panoptic mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the instance id, and the value is the corresponding attributes. all_category_ids: The dict of the category id in this mask, which key is the instance id, and the value is the corresponding category id. """ _repr_attrs = ("all_category_ids", "all_attributes") all_attributes: Dict[int, AttributeType] def __init__(self) -> None: self.all_category_ids: Dict[int, int] = {}
[docs]class SemanticMask(SemanticMaskBase, FileMixin): """SemanticMask is a class for the local semantic mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the category id, and the value is the corresponding attributes. """ def __init__(self, local_path: str) -> None: FileMixin.__init__(self, local_path)
[docs] def get_callback_body(self) -> Dict[str, Any]: """Get the callback request body for uploading. Returns: The callback request body, which looks like:: { "checksum": <str>, "fileSize": <int>, "info": [ { "categoryId": 0, "attributes": { "occluded": True } }, { "categoryId": 1, "attributes": { "occluded": False } } ] } """ body = super()._get_callback_body() if hasattr(self, "all_attributes"): body["info"] = [ {"categoryId": i, "attributes": attributes} for i, attributes in self.all_attributes.items() ] return body
[docs]class InstanceMask(InstanceMaskBase, FileMixin): """InstanceMask is a class for the local instance mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the instance id, and the value is the corresponding attributes. """ def __init__(self, local_path: str) -> None: FileMixin.__init__(self, local_path)
[docs] def get_callback_body(self) -> Dict[str, Any]: """Get the callback request body for uploading. Returns: The callback request body, which looks like:: { "checksum": <str>, "fileSize": <int>, "info": [ { "instanceId": 0, "attributes": { "occluded": True } }, { "instanceId": 1, "attributes": { "occluded": False } } ] } """ body = super()._get_callback_body() if hasattr(self, "all_attributes"): body["info"] = [ {"instanceId": i, "attributes": attributes} for i, attributes in self.all_attributes.items() ] return body
[docs]class PanopticMask(PanopticMaskBase, FileMixin): """PanopticMask is a class for the local panoptic mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the instance id, and the value is the corresponding attributes. all_category_ids: The dict of the category id in this mask, which key is the instance id, and the value is the corresponding category id. """ def __init__(self, local_path: str) -> None: PanopticMaskBase.__init__(self) FileMixin.__init__(self, local_path)
[docs] def get_callback_body(self) -> Dict[str, Any]: """Get the callback request body for uploading. Returns: The callback request body, which looks like:: { "checksum": <str>, "fileSize": <int>, "info": [ { "instanceId": 0, "categoryId": 100, "attributes": { "occluded": True } }, { "instanceId": 1, "categoryId": 101, "attributes": { "occluded": False } } ] } """ body = super()._get_callback_body() all_attributes = getattr(self, "all_attributes", None) info = [] for i, category_id in self.all_category_ids.items(): item = {"instanceId": i, "categoryId": category_id} if all_attributes: item["attributes"] = all_attributes[i] # pylint: disable=unsubscriptable-object info.append(item) body["info"] = info return body
[docs]class RemoteSemanticMask(SemanticMaskBase, RemoteFileMixin): """RemoteSemanticMask is a class for the remote semantic mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the category id, and the value is the corresponding attributes. """ _T = TypeVar("_T", bound="RemoteSemanticMask")
[docs] @classmethod def from_response_body(cls: Type[_T], body: Dict[str, Any]) -> _T: """Loads a :class:`RemoteSemanticMask` object from a response body. Arguments: body: The response body which contains the information of a remote semantic mask, whose format should be like:: { "remotePath": <str>, "info": [ { "categoryId": 0, "attributes": { "occluded": True } }, { "categoryId": 1, "attributes": { "occluded": False } } ] } Returns: The loaded :class:`RemoteSemanticMask` object. """ mask = cls(body["remotePath"]) if "info" in body: mask.all_attributes = {item["categoryId"]: item["attributes"] for item in body["info"]} return mask
[docs]class RemoteInstanceMask(InstanceMaskBase, RemoteFileMixin): """RemoteInstanceMask is a class for the remote instance mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the instance id, and the value is the corresponding attributes. """ _T = TypeVar("_T", bound="RemoteInstanceMask")
[docs] @classmethod def from_response_body(cls: Type[_T], body: Dict[str, Any]) -> _T: """Loads a :class:`RemoteInstanceMask` object from a response body. Arguments: body: The response body which contains the information of a remote instance mask, whose format should be like:: { "remotePath": <str>, "info": [ { "instanceId": 0, "attributes": { "occluded": True } }, { "instanceId": 1, "attributes": { "occluded": False } } ] } Returns: The loaded :class:`RemoteInstanceMask` object. """ mask = cls(body["remotePath"]) if "info" in body: mask.all_attributes = {item["instanceId"]: item["attributes"] for item in body["info"]} return mask
[docs]class RemotePanopticMask(PanopticMaskBase, RemoteFileMixin): """RemotePanoticMask is a class for the remote panotic mask label. Attributes: all_attributes: The dict of the attributes in this mask, which key is the instance id, and the value is the corresponding attributes. """ _T = TypeVar("_T", bound="RemotePanopticMask") def __init__( self, remote_path: str, *, _url_getter: Optional[Callable[[str], str]] = None ) -> None: PanopticMaskBase.__init__(self) RemoteFileMixin.__init__(self, remote_path, _url_getter=_url_getter)
[docs] @classmethod def from_response_body(cls: Type[_T], body: Dict[str, Any]) -> _T: """Loads a :class:`RemotePanopticMask` object from a response body. Arguments: body: The response body which contains the information of a remote panoptic mask, whose format should be like:: { "remotePath": <str>, "info": [ { "instanceId": 0, "categoryId": 100, "attributes": { "occluded": True } }, { "instanceId": 1, "categoryId": 101, "attributes": { "occluded": False } } ] } Returns: The loaded :class:`RemotePanopticMask` object. """ mask = cls(body["remotePath"]) info = body["info"] mask.all_category_ids = {item["instanceId"]: item["categoryId"] for item in info} if "attributes" in info[0]: mask.all_attributes = {item["instanceId"]: item["attributes"] for item in body["info"]} return mask