reid_hit_counter not reset when track is matched right before becoming dead
Describe the bug
TrackedObject tohashit_counter_max=5and is using RE-IDtois initialized andhit_counter=5(has been tracked continuously for at least 5 frames)Tracker.updateis called 5 times andtois not matchedto.hit_counteris now 0
Tracker.updateis called againtois added to the list ofalive_objectsper the check inTrackedObject.hit_counter_is_positive(return self.hit_counter >= 0)TrackedObject.tracker_stepis called on each tracked objecttohas itsreid_hit_counterset toreid_hit_counter_maxbecause of the>= 0check on this line.
togets "hit" by a detection in the current frametohas its hit counter incremented back up to 1 (tois alive and well now)- When
tois hit, itsreid_hit_counteris not set back toNone. This means that regardless of how it is tracked moving forward (it could be seen in every frame from here on and have a high and healthyhit_counter) it will have itsreid_hit_counterdecremented on each call toTracker.updateand afterreid_hit_counter_maxframes, it will be purged due to this code.
To Reproduce
- Create a
Trackerwith RE-ID enabled - Create a
Detectionto be sent to the tracker - Call
Tracker.updatewith the detection until there is aTrackedObjectwith a healthyhit_counter - Call
Tracker.updatewithout the detection until theTrackedObjecthas ahit_counterof 0 - Call
Tracker.updatewith the detectionreid_hit_counter_maxmore times - The
TrackedObjectwill be deleted
Code:
from norfair import Detection, Tracker
import numpy as np
tracker=Tracker(
distance_function="euclidean",
distance_threshold=0.1,
detection_threshold=0.1,
initialization_delay=0,
hit_counter_max=5,
reid_distance_function="euclidean",
reid_distance_threshold=0.1,
reid_hit_counter_max=5,
)
bbox = np.array([[10, 10], [20, 20]])
detection = Detection(
points=bbox,
scores=np.array([1.0, 1.0]),
label=1,
)
# Create healthy track
for i in range(5):
tracker.update(detections=[detection])
# Print healthy track
for i,to in enumerate(tracker.tracked_objects):
print(f'TO {i}: ', repr(to), f'(reid_hit_counter: {to.reid_hit_counter})')
# Lose track for hit_counter_max frames
for i in range(5):
tracker.update(detections=[])
# Print about to be pruned track
for i,to in enumerate(tracker.tracked_objects):
print(f'TO {i}: ', repr(to), f'(reid_hit_counter: {to.reid_hit_counter})')
# Match track
tracker.update(detections=[detection])
# Show that reid_hit_counter has been activated even though track was matched and hit_counter is positive
for i,to in enumerate(tracker.tracked_objects):
print(f'TO {i}: ', repr(to), f'(reid_hit_counter: {to.reid_hit_counter})')
# 6 more healthy matches (track considered alive when reid_hit_counter=0, so need 1 extra)
for i in range(6):
tracker.update(detections=[detection])
# Show that despite maxed out hit_counter, track is about to be pruned due to low reid_hit_counter
for i,to in enumerate(tracker.tracked_objects):
print(f'TO {i}: ', repr(to), f'(reid_hit_counter: {to.reid_hit_counter})')
# One more update will cause healthy track to be pruned
# NOTE: with initialization_delay=0, if we were to pass `detection` in here,
# the tracker would prune the existing `TrackedObject` and start a new one.
# If we pass nothing, it will simply delete the track
tracker.update(detections=[])
# Show that track has now been pruned
print("Number of tracked objects: ", len(tracker.tracked_objects))
"""
At this point, we would expect the `TrackedObject` to exist with a hit_counter of 4.
Instead it has been pruned
"""
Output:
TO 0: Object_1(age: 4, hit_counter: 5, last_distance: 0.00, init_id: 1) (reid_hit_counter: None)
TO 0: Object_1(age: 9, hit_counter: 0, last_distance: 0.00, init_id: 1) (reid_hit_counter: None)
TO 0: Object_1(age: 10, hit_counter: 1, last_distance: 0.00, init_id: 1) (reid_hit_counter: 5)
TO 0: Object_1(age: 16, hit_counter: 5, last_distance: 0.00, init_id: 1) (reid_hit_counter: -1)
Number of tracked objects: 0
Expected behavior
The TrackedObject should not be deleted
Environment (please complete the following information):
- OS: Mac OS Sonoma 14.3
- Python version: 3.9.19
- Norfair version: 2.2.0
I will try to get a PR out for this
Hello @joaqo @dekked @javiber @facundo-lezama! @robbinsa530 discovered a bug relating to the reid_hit_counter while using Norfair. We are big fans of the library at our company and wanted to contribute this change back to the repo. Any chance you could help us out here? We are happy to do the leg work, just need an approval from someone with write access and a new release once the change has been merged
Hey @robbinsa530 @treygilliland, thanks for reaching out! It's great to hear that you're using and liking Norfair, that's why we love open-source!
Thanks for the detailed explanation and for providing the code to test it. Let me go over it and review the PR.