Skip to content

Commit

Permalink
Fix reid track pruning bug Issue 325
Browse files Browse the repository at this point in the history
  • Loading branch information
robbinsa530 committed Dec 6, 2024
1 parent ac9c00b commit 85ebf83
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 0 deletions.
7 changes: 7 additions & 0 deletions norfair/tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,13 @@ def hit(self, detection: "Detection", period: int = 1):
self.is_initializing = False
self._acquire_ids()

# Reset reid_hit_counter if we are are successfully tracking this object.
# If hit_counter was 0 when Tracker.update was called and ReID is being used,
# we preemptively set reid_hit_counter to reid_hit_counter_max. But if the object
# is hit, we need to reset it.
if self.hit_counter_is_positive:
self.reid_hit_counter = None

# We use a kalman filter in which we consider each coordinate on each point as a sensor.
# This is a hacky way to update only certain sensors (only x, y coordinates for
# points which were detected).
Expand Down
53 changes: 53 additions & 0 deletions tests/test_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,59 @@ def dist(new_obj, tracked_obj):
assert tracked_objects[0].id != obj_id


def test_reid_hit_counter_reset():
#
# test that reid hit counter resets to None if it had started counting down but
# then the track was hit with an incoming detection
#

# simple reid distance
def dist(new_obj, tracked_obj):
return np.linalg.norm(new_obj.estimate - tracked_obj.estimate)

hit_counter_max = 2
reid_hit_counter_max = 2

tracker = Tracker(
distance_function="euclidean",
distance_threshold=1,
hit_counter_max=hit_counter_max,
initialization_delay=1,
reid_distance_function=dist,
reid_distance_threshold=5,
reid_hit_counter_max=reid_hit_counter_max,
)

# check that hit counters initialize correctly
tracked_objects = tracker.update([Detection(points=np.array([[1, 1]]))])
tracked_objects = tracker.update([Detection(points=np.array([[1, 1]]))])
assert len(tracked_objects) == 1
assert tracked_objects[0].hit_counter == 2
assert tracked_objects[0].reid_hit_counter == None

# check that object is still alive when hit_counter goes to 0
obj_id = tracked_objects[0].id
for _ in range(hit_counter_max):
tracked_objects = tracker.update()
assert len(tracked_objects) == 1
assert tracked_objects[0].hit_counter == 0
assert tracked_objects[0].reid_hit_counter is None

# check that object is alive and reid_hit_counter is None after being matched again
tracked_objects = tracker.update([Detection(points=np.array([[1, 1]]))])
assert len(tracked_objects) == 1
assert tracked_objects[0].hit_counter == 1
assert tracked_objects[0].reid_hit_counter is None

# check that after reid_hit_counter_max more updates, object still exists
for _ in range(reid_hit_counter_max + 2):
tracked_objects = tracker.update([Detection(points=np.array([[1, 1]]))])
assert len(tracked_objects) == 1
assert tracked_objects[0].hit_counter == 2
assert tracked_objects[0].reid_hit_counter is None
assert tracked_objects[0].id == obj_id


# TODO tests list:
# - detections with different labels
# - partial matches where some points are missing
Expand Down

0 comments on commit 85ebf83

Please sign in to comment.