Source code for dtlpy.entities.annotation_definitions.box

import numpy as np
from . import BaseAnnotationDefinition
from .polygon import Polygon


[docs]class Box(BaseAnnotationDefinition): """ Box annotation object Can create a box using 2 point using: "top", "left", "bottom", "right" (to form a box [(left, top), (right, bottom)]) For rotated box add the "angel" """ type = "box" def __init__(self, left=None, top=None, right=None, bottom=None, label=None, attributes=None, description=None, angle=None): """ Can create a box using 2 point using: "top", "left", "bottom", "right" (to form a box [(left, top), (right, bottom)]) And for create a rotated box need to add the angle of the rotation :param left: left x coordinate of the box :param top: top Y coordinate of the box :param right: right x coordinate of the box :param bottom: bottom Y coordinate of the box :param label: annotation label :param attributes: a list of attributes for the annotation :param description: :param angle: the angle of the rotation in degrees :return: """ super().__init__(description=description, attributes=attributes) self.angle = angle self.left = left self.top = top self.right = right self.bottom = bottom self.top_left = [left, top] self.top_right = [right, top] self.bottom_left = [left, bottom] self.bottom_right = [right, bottom] self.label = label @property def x(self): return [self.left, self.right] @property def y(self): return [self.top, self.bottom] @property def geo(self): return [ [self.left, self.top], [self.right, self.bottom] ] @property def four_points(self): return [self.top_left, self.bottom_left, self.bottom_right, self.top_right]
[docs] def show(self, image, thickness, with_text, height, width, annotation_format, color, alpha=1): """ Show annotation as ndarray :param image: empty or image to draw on :param thickness: :param with_text: not required :param height: item height :param width: item width :param annotation_format: options: list(dl.ViewAnnotationOptions) :param color: color :param alpha: opacity value [0 1], default 1 :return: ndarray """ try: import cv2 except (ImportError, ModuleNotFoundError): self.logger.error( 'Import Error! Cant import cv2. Annotations operations will be limited. import manually and fix errors') raise if thickness is None: thickness = 2 # draw annotation points = self.four_points # create image to draw on if alpha != 1: overlay = image.copy() else: overlay = image # draw annotation overlay = cv2.drawContours( image=overlay, contours=[np.round(points).astype(int)], contourIdx=-1, color=color, thickness=thickness, lineType=cv2.LINE_AA ) if not isinstance(color, int) and len(color) == 4 and color[3] != 255: # add with opacity image = cv2.addWeighted(src1=overlay, alpha=alpha, src2=image, beta=1 - alpha, gamma=0) else: image = overlay if with_text: image = self.add_text_to_image(image=image, annotation=self) return image
def to_coordinates(self, color): points = [ [self.left, self.top], [self.right, self.bottom] ] pts = [{"x": float(x), "y": float(y), "z": 0} for x, y in points] if self.angle is not None and self.angle != 0: pts.append(self.angle) return pts @staticmethod def from_coordinates(coordinates): return np.asarray([[pt["x"], pt["y"]] for pt in coordinates[:2]]) @classmethod def from_json(cls, _json): coordinates = _json.get("coordinates", None) if "coordinates" in _json else _json.get("data", None) if coordinates is None: raise ValueError('can not find "coordinates" or "data" in annotation. id: {}'.format(_json["id"])) geo = cls.from_coordinates(coordinates=coordinates) left = np.min(geo[:, 0]) top = np.min(geo[:, 1]) right = np.max(geo[:, 0]) bottom = np.max(geo[:, 1]) angel = coordinates[2] if len(coordinates) > 2 and ( isinstance(coordinates[2], float) or isinstance(coordinates[2], int)) else None return cls( left=left, top=top, right=right, bottom=bottom, label=_json["label"], attributes=_json.get("attributes", None), angle=angel )
[docs] @classmethod def from_segmentation(cls, mask, label, attributes=None): """ Convert binary mask to Polygon :param mask: binary mask (0,1) :param label: annotation label :param attributes: annotations list of attributes :return: Box annotations list to each separated segmentation """ polygons = Polygon.from_segmentation( mask=mask, label=label, attributes=attributes, max_instances=None ) if not isinstance(polygons, list): polygons = [polygons] boxes = [ cls( left=polygon.left, top=polygon.top, right=polygon.right, bottom=polygon.bottom, label=label, attributes=attributes ) for polygon in polygons ] return boxes