Coverage for backpack/annotation/driver.py: 100%
43 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-30 23:12 +0000
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-30 23:12 +0000
1import logging
2from .annotation import Annotation
3from typing import Iterable, Optional, Any
4from abc import ABC, abstractmethod
6from ..geometry import Point
7from .annotation import (
8 MarkerAnnotation, RectAnnotation, LabelAnnotation, LineAnnotation, PolyLineAnnotation,
9 BoundingBoxAnnotation
10)
12class AnnotationDriverBase(ABC):
13 ''' Base class for annotating drawing drivers.
15 Annotation drivers provide an unified API to draw annotations on images of different backends.
16 All annotation driver should derive from `AnnotationDriverBase`.
18 Args:
19 parent_logger: If you want to connect the logger of the annotation driver to a parent,
20 specify it here.
21 '''
22 def __init__(self, parent_logger: Optional[logging.Logger] = None):
23 self.logger = (
24 logging.getLogger(self.__class__.__name__) if parent_logger is None else
25 parent_logger.getChild(self.__class__.__name__)
26 )
28 def render(self,
29 annotations: Iterable[Annotation],
30 context: Any
31 ) -> Any:
32 ''' Renders a collection of annotations on a context.
34 Args:
35 annotations: An iterable collection of annotation type defined in this module.
36 context: The context of the backend. Type is implementation-specific.
38 Returns:
39 The context.
40 '''
41 for anno in annotations:
42 if isinstance(anno, LabelAnnotation):
43 self.add_label(anno, context)
44 elif isinstance(anno, RectAnnotation):
45 self.add_rect(anno, context)
46 elif isinstance(anno, MarkerAnnotation):
47 self.add_marker(anno, context)
48 elif isinstance(anno, LineAnnotation):
49 self.add_line(anno, context)
50 elif isinstance(anno, PolyLineAnnotation):
51 self.add_polyline(anno, context)
52 elif isinstance(anno, BoundingBoxAnnotation):
53 self.add_bounding_box(anno, context)
54 else:
55 raise ValueError(f'Unknown annotation type: {type(anno)}')
56 return context
58 @abstractmethod
59 def add_rect(self, rect: RectAnnotation, context: Any) -> None:
60 ''' Renders a rectangle on the frame.
62 Args:
63 rect: A rectangle annotation.
64 context: A backend-specific context object that was passed to the :meth:`render` method.
65 '''
67 @abstractmethod
68 def add_label(self, label: LabelAnnotation, context: Any) -> None:
69 ''' Renders a label on the frame.
71 Args:
72 label: A label annotation.
73 context: A backend-specific context object that was passed to the :meth:`render` method.
74 '''
76 @abstractmethod
77 def add_marker(self, marker: MarkerAnnotation, context: Any) -> None:
78 ''' Renders a marker on the frame.
80 Args:
81 marker: A marker annotation.
82 context: A backend-specific context object that was passed to the :meth:`render` method.
83 '''
85 @abstractmethod
86 def add_line(self, label: LineAnnotation, context: Any) -> None:
87 ''' Renders a line on the frame.
89 Args:
90 line: A line annotation.
91 context: A backend-specific context object that was passed to the :meth:`render` method.
92 '''
94 @abstractmethod
95 def add_polyline(self, polyline: PolyLineAnnotation, context: Any) -> None:
96 ''' Renders a polyline.
98 Args:
99 polyline: A polyline annotation.
100 context: A backend-specific context object that was passed to the :meth:`render` method.
101 '''
103 def add_bounding_box(self, bounding_box: BoundingBoxAnnotation, context: Any) -> None:
104 ''' Renders a bounding box.
106 Args:
107 bounding_box: A bounding box annotation.
108 context: A backend-specific context object that was passed to the :meth:`render` method.
109 '''
110 rect = bounding_box.rectangle
111 annos = [RectAnnotation(rect=rect, color=bounding_box.color)]
112 if bounding_box.top_label:
113 annos.append(
114 LabelAnnotation(
115 point=rect.pt_min,
116 text=bounding_box.top_label,
117 color=bounding_box.color,
118 horizontal_anchor=LabelAnnotation.HorizontalAnchor.LEFT,
119 vertical_anchor=LabelAnnotation.VerticalAnchor.BOTTOM
120 )
121 )
122 if bounding_box.bottom_label:
123 annos.append(
124 LabelAnnotation(
125 point=Point(rect.pt_min.x, rect.pt_max.y),
126 text=bounding_box.bottom_label,
127 color=bounding_box.color,
128 horizontal_anchor=LabelAnnotation.HorizontalAnchor.LEFT,
129 vertical_anchor=LabelAnnotation.VerticalAnchor.TOP
130 )
131 )
132 self.render(annos, context)