Skip to content

Commit

Permalink
fix: is_box_in_image function
Browse files Browse the repository at this point in the history
Signed-off-by: ktro2828 <[email protected]>
  • Loading branch information
ktro2828 committed Dec 3, 2024
1 parent 22463c4 commit 9515929
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 10 deletions.
18 changes: 9 additions & 9 deletions t4_devkit/common/geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def view_points(
points = points[:3, :]

if normalize:
points = points / points[2:3, :].repeat(3, 0).reshape(3, nbr_points)
points /= points[2:3, :]

return points

Expand All @@ -90,21 +90,21 @@ def is_box_in_image(
Returns:
Return True if visibility condition is satisfied.
"""
corners_3d = box.corners()
corners_on_img = view_points(corners_3d.T, intrinsic, normalize=True)[:2, :]
corners_3d = box.corners().T # (3, 8)
corners_on_img = view_points(corners_3d, intrinsic, normalize=True)[:2, :]

img_w, img_h = img_size
is_visible = np.logical_and(corners_on_img[0, :] > 0, corners_on_img[0, :] < img_w)
is_visible = np.logical_and(is_visible, corners_on_img[1, :] < img_h)
is_visible = np.logical_and(is_visible, corners_on_img[1, :] > 0)
is_visible = np.logical_and(is_visible, corners_on_img[2, :] > 1)
is_visible = np.logical_and(corners_on_img[0, :] >= 0, corners_on_img[0, :] <= img_w)
is_visible = np.logical_and(is_visible, corners_on_img[1, :] <= img_h)
is_visible = np.logical_and(is_visible, corners_on_img[1, :] >= 0)
is_visible = np.logical_and(is_visible, corners_3d[2, :] > 1)

in_front = corners_3d[2, :] > 0.1 # True if a corner is at least 0.1 meter in front of camera.

if visibility == VisibilityLevel.FULL:
return all(is_visible) and all(in_front)
return np.all(is_visible) and np.all(in_front)
elif visibility in (VisibilityLevel.MOST, VisibilityLevel.PARTIAL):
return any(is_visible)
return np.any(is_visible)
elif visibility == VisibilityLevel.NONE:
return True
else:
Expand Down
46 changes: 45 additions & 1 deletion tests/common/test_geometry.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np

from t4_devkit.common.geometry import view_points
from t4_devkit.common.geometry import is_box_in_image, view_points
from t4_devkit.schema import VisibilityLevel


def test_view_points_by_perspective_projection() -> None:
Expand Down Expand Up @@ -77,3 +78,46 @@ def test_view_points_with_distortion() -> None:
)

assert np.allclose(project, expect)


# TODO(ktro2828): add unit testing for VisibilityLevel.FULL


def test_box_partial_visible(dummy_box3d, dummy_camera_calibration) -> None:
"""Test `is_box_in_image` function in the case of the box is partially visible."""
img_size, intrinsic = dummy_camera_calibration

dummy_box3d.position = (0.0, 0.0, 2.0)
assert is_box_in_image(
dummy_box3d,
intrinsic=intrinsic,
img_size=img_size,
visibility=VisibilityLevel.PARTIAL,
)


def test_box_not_visible(dummy_box3d, dummy_camera_calibration) -> None:
"""Test `is_box_in_image` function in the case of the box is not visible."""
img_size, intrinsic = dummy_camera_calibration

dummy_box3d.position = (100.0, 100.0, 1.0)
assert not is_box_in_image(
dummy_box3d,
intrinsic=intrinsic,
img_size=img_size,
visibility=VisibilityLevel.PARTIAL,
)


def test_box_behind_camera(dummy_box3d, dummy_camera_calibration) -> None:
"""Test `is_box_in_image` function in the case of the box is behind of the camera."""

img_size, intrinsic = dummy_camera_calibration

dummy_box3d.position = (100.0, 100.0, -1.0)
assert not is_box_in_image(
dummy_box3d,
intrinsic=intrinsic,
img_size=img_size,
visibility=VisibilityLevel.FULL,
)
23 changes: 23 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
from __future__ import annotations

from typing import TYPE_CHECKING

import numpy as np
import pytest
from pyquaternion import Quaternion

Expand All @@ -12,6 +17,9 @@
TransformBuffer,
)

if TYPE_CHECKING:
from t4_devkit.typing import NDArrayFloat


@pytest.fixture(scope="module")
def label2id() -> dict[str, int]:
Expand Down Expand Up @@ -176,3 +184,18 @@ def dummy_tf_buffer() -> TransformBuffer:
)

return tf_buffer


@pytest.fixture(scope="function")
def dummy_camera_calibration() -> tuple[tuple[int, int], NDArrayFloat]:
img_size = (1280, 720)

intrinsic = np.array(
[
[1000, 0, 640],
[0, 1000, 360],
[0, 0, 1],
]
)

return img_size, intrinsic

0 comments on commit 9515929

Please sign in to comment.