Skip to content

Commit 42f66b2

Browse files
committed
refactor: update detection/tracking metrics (#136)
Signed-off-by: ktro2828 <kotaro.uetake@tier4.jp>
1 parent 24ba3d1 commit 42f66b2

4 files changed

Lines changed: 24 additions & 85 deletions

File tree

t4_devkit/evaluation/matching/parameter.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ class MatchingScorer(str, Enum):
8787
PLANE_DISTANCE = "PLANE_DISTANCE"
8888
IOU2D = "IOU2D"
8989
IOU3D = "IOU3D"
90-
HEADING_YAW = "HEADING_YAW"
9190

9291

9392
class MatchingPolicy(str, Enum):

t4_devkit/evaluation/matching/scorer.py

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
"PlaneDistance",
2020
"Iou2D",
2121
"Iou3D",
22-
"HeadingYaw",
2322
]
2423

2524

@@ -246,61 +245,3 @@ def _calculate_score(
246245
intersection = compute_volume_intersection(box1, box2)
247246
union = box1.volume + box2.volume - intersection
248247
return intersection / union
249-
250-
251-
class HeadingYaw(MatchingScorerImpl):
252-
def _validate(self, box1, box2):
253-
super()._validate(box1, box2)
254-
255-
if not isinstance(box1, Box3D):
256-
raise TypeError("For Iou3D, input boxes must be 3D.")
257-
258-
@classmethod
259-
def is_smaller_score_better(cls) -> bool:
260-
return True
261-
262-
def _calculate_score(
263-
self,
264-
box1: Box3D,
265-
box2: Box3D,
266-
ego2map: HomogeneousMatrix | None = None,
267-
) -> float:
268-
box1 = self._transform2ego(box1, ego2map)
269-
box2 = self._transform2ego(box2, ego2map)
270-
271-
return abs(box2.diff_yaw(box1))
272-
273-
def _transform2ego(self, box: Box3D, ego2map: HomogeneousMatrix | None = None) -> Box3D:
274-
"""Transform the box to base link frame if it is not.
275-
276-
Todo:
277-
This method should be function.
278-
"""
279-
if box.frame_id == "base_link":
280-
return box
281-
282-
if ego2map is None:
283-
raise ValueError(f"For {box.frame_id}, `ego2map` must be specified.")
284-
285-
matrix = HomogeneousMatrix(
286-
position=box.position,
287-
rotation=box.rotation,
288-
src=box.frame_id,
289-
dst="base_link",
290-
)
291-
292-
tf = ego2map.inv().transform(matrix=matrix)
293-
294-
return Box3D(
295-
unix_time=box.unix_time,
296-
frame_id="base_link",
297-
semantic_label=box.semantic_label,
298-
position=tf.position,
299-
rotation=tf.rotation,
300-
shape=box.shape,
301-
velocity=box.velocity,
302-
num_points=box.num_points,
303-
future=box.future,
304-
confidence=box.confidence,
305-
uuid=box.uuid,
306-
)

t4_devkit/evaluation/metric/ap.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,8 @@
55
import numpy as np
66
from attrs import define, field
77

8-
from ..matching import CenterDistance, HeadingYaw
9-
108
if TYPE_CHECKING:
11-
from t4_devkit.evaluation import FrameBoxMatch, MatchingScorerLike
9+
from t4_devkit.evaluation import BoxMatch, FrameBoxMatch, MatchingScorerLike
1210

1311
__all__ = ["Ap", "ApH"]
1412

@@ -61,18 +59,18 @@ def compute_ap(self) -> float:
6159

6260
return float(np.mean(filtered_precision)) / (1.0 - Ap.min_precision)
6361

64-
def __init__(self, threshold: float) -> None:
65-
self.scorer = self._configure_scorer()
62+
def __init__(self, scorer: MatchingScorerLike, threshold: float) -> None:
63+
self.scorer = scorer
6664
self.threshold = threshold
6765

68-
def _configure_scorer(self) -> MatchingScorerLike:
69-
return CenterDistance()
70-
7166
def __call__(self, frames: list[FrameBoxMatch]) -> float:
72-
component = self._compute_tp_fp(frames)
73-
return component.compute_ap()
67+
buffer = self._update_buffer(frames)
68+
return buffer.compute_ap()
7469

75-
def _compute_tp_fp(self, frames: list[FrameBoxMatch]) -> ApBuffer:
70+
def _compute_tp(self, _box_match: BoxMatch) -> float:
71+
return 1.0
72+
73+
def _update_buffer(self, frames: list[FrameBoxMatch]) -> ApBuffer:
7674
buffer = self.ApBuffer()
7775
for frame in frames:
7876
buffer.num_gt += frame.num_gt
@@ -86,7 +84,7 @@ def _compute_tp_fp(self, frames: list[FrameBoxMatch]) -> ApBuffer:
8684
threshold=self.threshold,
8785
ego2map=frame.ego2map,
8886
):
89-
buffer.tp_list.append(1.0)
87+
buffer.tp_list.append(self._compute_tp(box_match))
9088
buffer.fp_list.append(0.0)
9189
else:
9290
buffer.tp_list.append(0.0)
@@ -98,5 +96,11 @@ class ApH(Ap):
9896
def __init__(self, threshold: float) -> None:
9997
super().__init__(threshold=threshold)
10098

101-
def _configure_scorer(self) -> HeadingYaw:
102-
return HeadingYaw()
99+
def _compute_tp(self, box_match: BoxMatch) -> float:
100+
if not box_match.is_matched():
101+
return 0.0
102+
103+
diff_yaw = box_match.estimation.diff_yaw(box_match.ground_truth)
104+
if diff_yaw > np.pi:
105+
diff_yaw = 2.0 * np.pi - diff_yaw
106+
return min(1.0, max(0.0, 1.0 - diff_yaw / np.pi))

t4_devkit/evaluation/metric/clear.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
from attrs import define, field
66

7-
from ..matching import CenterDistance
8-
97
if TYPE_CHECKING:
108
from t4_devkit.evaluation import BoxMatch, FrameBoxMatch, MatchingScorerLike
119

@@ -31,18 +29,15 @@ def compute_mota(self) -> float:
3129
def compute_motp(self) -> float:
3230
return max(self.score / self.num_tp, 0.0) if self.num_tp > 0 else 0.0
3331

34-
def __init__(self, threshold: float) -> None:
35-
self.scorer = self._configure_scorer()
32+
def __init__(self, scorer: MatchingScorerLike, threshold: float) -> None:
33+
self.scorer = scorer
3634
self.threshold = threshold
3735

38-
def _configure_scorer(self) -> MatchingScorerLike:
39-
return CenterDistance()
40-
4136
def __call__(self, frames: list[FrameBoxMatch]) -> float:
42-
buffer = self._compute_clear(frames)
37+
buffer = self._update_buffer(frames)
4338
return buffer.compute_mota()
4439

45-
def _compute_clear(self, frames: list[FrameBoxMatch]) -> ClearBuffer:
40+
def _update_buffer(self, frames: list[FrameBoxMatch]) -> ClearBuffer:
4641
buffer = self.ClearBuffer()
4742
num_frame = len(frames)
4843
for i in range(1, num_frame):
@@ -75,7 +70,7 @@ def _compute_clear(self, frames: list[FrameBoxMatch]) -> ClearBuffer:
7570
buffer.score += self.scorer(
7671
previous_match.estimation,
7772
previous_match.ground_truth,
78-
previous_frame.ego2map,
73+
ego2map=previous_frame.ego2map,
7974
)
8075
break
8176

@@ -129,5 +124,5 @@ def _check_match(
129124

130125
class Motp(Mota):
131126
def __call__(self, frames: list[FrameBoxMatch]) -> float:
132-
buffer = self._compute_clear(frames)
127+
buffer = self._update_buffer(frames)
133128
return buffer.compute_motp()

0 commit comments

Comments
 (0)