from dataclasses import dataclass, field, InitVar
from typing import Optional
[docs]
@dataclass(slots=True)
class COCOCoordinates:
"""
A class to represent bounding box coordinates in (x, y, width, height) format.
Attributes:
x (float): The top-left corner x coordinate.
y (float): The top-left corner y coordinate.
w (float): The width of the box.
h (float): The height of the box.
"""
# Properties
x: int = field(init=False)
y: int = field(init=False)
w: int = field(init=False)
h: int = field(init=False)
# Init-only fields
input_x: InitVar[int]
input_y: InitVar[int]
input_w: InitVar[int]
input_h: InitVar[int]
image_height: InitVar[Optional[int]] = field(default=None, kw_only=True)
def __post_init__(self, input_x: int, input_y: int, input_w: int, input_h: int, image_height: Optional[int]):
if image_height is None:
self.x = input_x
self.y = input_y
self.w = input_w
self.h = input_h
else:
self.x = input_x
self.y = image_height - (input_y + input_h)
self.w = input_w
self.h = input_h
def __str__(self):
return f"[{self.x}, {self.y}, {self.w}, {self.h}]"
def __iter__(self):
return iter((self.x, self.y, self.w, self.h))
[docs]
def to_xyxy(self):
"""
Convert the (x, y, w, h) coordinates to XYXY format (x_min, y_min, x_max, y_max).
"""
x_max = self.x + self.w
y_max = self.y + self.h
return XYXYCoordinates(self.x, self.y, x_max, y_max)
[docs]
@dataclass(slots=True)
class XYXYCoordinates:
"""
A class to represent bounding box coordinates in (x_min, y_min, x_max, y_max) format.
Attributes:
x_min (float): The minimum x-coordinate (left).
y_min (float): The minimum y-coordinate (top).
x_max (float): The maximum x-coordinate (right).
y_max (float): The maximum y-coordinate (bottom).
"""
x_min: int
y_min: int
x_max: int
y_max: int
def __str__(self) -> str:
return f"[{self.x_min}, {self.y_min}, {self.x_max}, {self.y_max}]"
def __iter__(self):
return iter((self.x_min, self.y_min, self.x_max, self.y_max))
[docs]
def to_coco(self):
"""
Convert the (x_min, y_min, x_max, y_max) coordinates to COCO format (x, y, width, height).
"""
width = self.x_max - self.x_min
height = self.y_max - self.y_min
return COCOCoordinates(self.x_min, self.y_min, width, height)