Skip to content
6 changes: 3 additions & 3 deletions t4_devkit/common/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
from pyquaternion import Quaternion

if TYPE_CHECKING:
from t4_devkit.typing import ArrayLike, NDArray
from t4_devkit.typing import RotationLike

__all__ = ["to_quaternion"]


def to_quaternion(x: ArrayLike | NDArray) -> Quaternion:
def to_quaternion(x: RotationLike) -> Quaternion:
"""Convert input rotation like array to `Quaternion`.

Args:
x (ArrayLike | NDArray): Rotation matrix or quaternion.
x (RotationLike): Rotation matrix or quaternion.

Returns:
Quaternion: Converted instance.
Expand Down
14 changes: 7 additions & 7 deletions t4_devkit/common/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@

if TYPE_CHECKING:
from t4_devkit.dataclass import Box3D
from t4_devkit.typing import NDArrayF64
from t4_devkit.typing import CameraDistortionLike, CameraIntrinsicLike, NDArrayF64


__all__ = ("view_points", "is_box_in_image")


def view_points(
points: NDArrayF64,
intrinsic: NDArrayF64,
distortion: NDArrayF64 | None = None,
intrinsic: CameraIntrinsicLike,
distortion: CameraDistortionLike | None = None,
*,
normalize: bool = True,
) -> NDArrayF64:
Expand All @@ -27,8 +27,8 @@ def view_points(

Args:
points (NDArrayF64): Matrix of points, which is the shape of (3, n) and (x, y, z) is along each column.
intrinsic (NDArrayF64): nxn camera intrinsic matrix (n <= 4).
distortion (NDArrayF64 | None, optional): Camera distortion coefficients, which is the shape of (n,) (n >= 5).
intrinsic (CameraIntrinsicLike): nxn camera intrinsic matrix (n <= 4).
distortion (CameraDistortionLike | None, optional): Camera distortion coefficients, which is the shape of (n,) (n >= 5).
normalize (bool, optional): Whether to normalize the remaining coordinate (along the 3rd axis).

Returns:
Expand Down Expand Up @@ -75,15 +75,15 @@ def view_points(

def is_box_in_image(
box: Box3D,
intrinsic: NDArrayF64,
intrinsic: CameraIntrinsicLike,
img_size: tuple[int, int],
visibility: VisibilityLevel = VisibilityLevel.NONE,
) -> bool:
"""Check if a box is visible inside of an image without considering its occlusions.

Args:
box (Box3D): The box to be checked.
intrinsic (NDArrayF64): 3x3 camera intrinsic matrix.
intrinsic (CameraIntrinsicLike): 3x3 camera intrinsic matrix.
img_size (tuple[int, int]): Image size in the order of (width, height).
visibility (VisibilityLevel, optional): Enum member of VisibilityLevel.

Expand Down
13 changes: 8 additions & 5 deletions t4_devkit/common/timestamp.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
from __future__ import annotations

from numbers import Number
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from t4_devkit.typing import ScalarLike

__all__ = ("us2sec", "sec2us")


def us2sec(timestamp: Number) -> float:
def us2sec(timestamp: ScalarLike) -> float:
"""Convert timestamp from micro seconds [us] to seconds [s].

Args:
timestamp (Number): Timestamp in [us].
timestamp (ScalarLike): Timestamp in [us].

Returns:
Timestamp in [s].
"""
return 1e-6 * timestamp


def sec2us(timestamp: Number) -> float:
def sec2us(timestamp: ScalarLike) -> float:
"""Convert timestamp from seconds [s] to micro seconds [us].

Args:
timestamp (Number): Timestamp in [s].
timestamp (ScalarLike): Timestamp in [s].

Returns:
Timestamp in [us].
Expand Down
33 changes: 0 additions & 33 deletions t4_devkit/common/validator.py

This file was deleted.

1 change: 0 additions & 1 deletion t4_devkit/dataclass/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from .box import * # noqa
from .label import * # noqa
from .pointcloud import * # noqa
from .roi import * # noqa
from .shape import * # noqa
from .trajectory import * # noqa
from .transform import * # noqa
52 changes: 25 additions & 27 deletions t4_devkit/dataclass/box.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@
from typing_extensions import Self

from t4_devkit.common.converter import to_quaternion
from t4_devkit.common.validator import is_vector3
from t4_devkit.schema import VisibilityLevel
from t4_devkit.typing import Quaternion, Roi, Vector3

from .label import SemanticLabel
from .roi import Roi
from .shape import Shape
from .trajectory import Future

if TYPE_CHECKING:
from t4_devkit.dataclass import HomogeneousMatrix
from t4_devkit.typing import ArrayLike, NDArrayF64, QuaternionLike, Vector3Like
from t4_devkit.typing import ArrayLike, NDArrayF64, RotationLike, ScalarLike, Vector3Like


__all__ = ["Box3D", "Box2D", "BoxLike", "distance_box"]
Expand Down Expand Up @@ -84,10 +83,10 @@ class Box3D(BaseBox):
semantic_label (SemanticLabel): `SemanticLabel` object.
confidence (float, optional): Confidence score of the box.
uuid (str | None, optional): Unique box identifier.
position (Vector3Like): Box center position (x, y, z).
rotation (QuaternionLike): Box rotation quaternion.
position (Vector3): Box center position (x, y, z).
rotation (Quaternion): Box rotation quaternion.
shape (Shape): `Shape` object.
velocity (Vector3Like | None, optional): Box velocity (vx, vy, vz).
velocity (Vector3 | None, optional): Box velocity (vx, vy, vz).
num_points (int | None, optional): The number of points inside the box.
visibility (VisibilityLevel, optional): Box visibility.
future (Future | None, optional): Box trajectory in the future of each mode.
Expand All @@ -99,7 +98,7 @@ class Box3D(BaseBox):
... frame_id="base_link",
... semantic_label=SemanticLabel("car"),
... position=(1.0, 1.0, 1.0),
... rotation=Quaternion([0.0, 0.0, 0.0, 1.0]),
... rotation=(0.0, 0.0, 0.0, 1.0),
... shape=Shape(shape_type=ShapeType.BOUNDING_BOX, size=(1.0, 1.0, 1.0)),
... velocity=(1.0, 1.0, 1.0),
... confidence=1.0,
Expand All @@ -112,14 +111,10 @@ class Box3D(BaseBox):
... )
"""

position: Vector3Like = field(converter=np.array, validator=is_vector3)
rotation: QuaternionLike = field(converter=to_quaternion)
position: Vector3 = field(converter=Vector3)
rotation: Quaternion = field(converter=to_quaternion)
shape: Shape = field(validator=validators.instance_of(Shape))
velocity: Vector3Like | None = field(
default=None,
converter=converters.optional(np.array),
validator=validators.optional(is_vector3),
)
velocity: Vector3 | None = field(default=None, converter=converters.optional(Vector3))
num_points: int | None = field(
default=None,
validator=validators.optional((validators.instance_of(int), validators.ge(0))),
Expand Down Expand Up @@ -168,7 +163,7 @@ def __eq__(self, other: Box3D | None) -> bool:
return eq

@property
def size(self) -> Vector3Like:
def size(self) -> Vector3:
"""Return the box size in the order of (width, length, height).

Returns:
Expand Down Expand Up @@ -199,12 +194,13 @@ def translate(self, x: Vector3Like) -> None:
if self.future is not None:
self.future.translate(x)

def rotate(self, q: QuaternionLike) -> None:
def rotate(self, q: RotationLike) -> None:
"""Apply a rotation.

Args:
q (QuaternionLike): Rotation quaternion.
q (RotationLike): Rotation quaternion.
"""
q = to_quaternion(q)
self.position = np.dot(q.rotation_matrix, self.position)
self.rotation = q * self.rotation

Expand Down Expand Up @@ -247,7 +243,7 @@ class Box2D(BaseBox):
confidence (float, optional): Confidence score of the box.
uuid (str | None, optional): Unique box identifier.
roi (Roi | None, optional): `Roi` object.
position (Vector3Like | None, optional): 3D position (x, y, z).
position (Vector3 | None, optional): 3D position (x, y, z).

Examples:
>>> # without 3D position
Expand All @@ -266,11 +262,13 @@ class Box2D(BaseBox):
roi: Roi | None = field(
default=None,
converter=lambda x: None if x is None else Roi(x),
validator=validators.optional(validators.instance_of(Roi)),
)

# additional attributes: set by `with_**`
position: Vector3Like | None = field(default=None, validator=validators.optional(is_vector3))
position: Vector3 | None = field(
default=None,
converter=lambda x: None if x is None else Vector3(x),
)

def with_position(self, position: Vector3Like) -> Self:
"""Return a self instance setting `position` attribute.
Expand All @@ -281,7 +279,7 @@ def with_position(self, position: Vector3Like) -> Self:
Returns:
Self instance after setting `position`.
"""
self.position = np.asarray(position)
self.position = Vector3(position)
return self

def __eq__(self, other: Box2D | None) -> bool:
Expand All @@ -295,27 +293,27 @@ def __eq__(self, other: Box2D | None) -> bool:
return eq

@property
def offset(self) -> tuple[int, int] | None:
def offset(self) -> tuple[ScalarLike, ScalarLike] | None:
return None if self.roi is None else self.roi.offset

@property
def size(self) -> tuple[int, int] | None:
def size(self) -> tuple[ScalarLike, ScalarLike] | None:
return None if self.roi is None else self.roi.size

@property
def width(self) -> int | None:
def width(self) -> ScalarLike | None:
return None if self.roi is None else self.roi.width

@property
def height(self) -> int | None:
def height(self) -> ScalarLike | None:
return None if self.roi is None else self.roi.height

@property
def center(self) -> tuple[int, int] | None:
def center(self) -> tuple[ScalarLike, ScalarLike] | None:
return None if self.roi is None else self.roi.center

@property
def area(self) -> int | None:
def area(self) -> ScalarLike | None:
return None if self.roi is None else self.roi.area


Expand Down
80 changes: 0 additions & 80 deletions t4_devkit/dataclass/roi.py

This file was deleted.

Loading
Loading