Tracking tweaks

- When registering new objects, use the past detections from Norfair to populate self.positions and self.stationary_box_history. This prevents the first call of update_position() from triggering a +1 on the object's stationary count (because the iou would be 1.0).
- Add a specific tracker for dedicated LPR cam license_plate objects using a lower R value and higher distance threshold to account for fast moving plates.
- Add helpful debug messages and keep them disabled with `if False:`
This commit is contained in:
Josh Hawkins 2025-04-12 16:15:55 -05:00
parent 039148397b
commit 2746b253c3

View File

@ -129,6 +129,11 @@ class NorfairTracker(ObjectTracker):
"distance_function": frigate_distance, "distance_function": frigate_distance,
"distance_threshold": 2.5, "distance_threshold": 2.5,
}, },
"license_plate": {
"filter_factory": OptimizedKalmanFilterFactory(R=2.5, Q=0.05),
"distance_function": frigate_distance,
"distance_threshold": 3.75,
},
} }
# Define autotracking PTZ-specific configurations # Define autotracking PTZ-specific configurations
@ -273,17 +278,24 @@ class NorfairTracker(ObjectTracker):
) )
self.tracked_objects[id] = obj self.tracked_objects[id] = obj
self.disappeared[id] = 0 self.disappeared[id] = 0
if obj_match:
boxes = [p.data["box"] for p in obj_match.past_detections]
else:
boxes = [obj["box"]]
xmins, ymins, xmaxs, ymaxs = zip(*boxes)
self.positions[id] = { self.positions[id] = {
"xmins": [], "xmins": list(xmins),
"ymins": [], "ymins": list(ymins),
"xmaxs": [], "xmaxs": list(xmaxs),
"ymaxs": [], "ymaxs": list(ymaxs),
"xmin": 0, "xmin": 0,
"ymin": 0, "ymin": 0,
"xmax": self.detect_config.width, "xmax": self.detect_config.width,
"ymax": self.detect_config.height, "ymax": self.detect_config.height,
} }
self.stationary_box_history[id] = [] self.stationary_box_history[id] = boxes
def deregister(self, id, track_id): def deregister(self, id, track_id):
obj = self.tracked_objects[id] obj = self.tracked_objects[id]
@ -369,9 +381,9 @@ class NorfairTracker(ObjectTracker):
} }
return False return False
# if there are less than 10 entries for the position, add the bounding box # if there are more than 5 and less than 10 entries for the position, add the bounding box
# and recompute the position box # and recompute the position box
if len(position["xmins"]) < 10: if 5 <= len(position["xmins"]) < 10:
position["xmins"].append(xmin) position["xmins"].append(xmin)
position["ymins"].append(ymin) position["ymins"].append(ymin)
position["xmaxs"].append(xmax) position["xmaxs"].append(xmax)
@ -599,7 +611,10 @@ class NorfairTracker(ObjectTracker):
# print a table to the console with norfair tracked object info # print a table to the console with norfair tracked object info
if False: if False:
self.print_objects_as_table(self.trackers["person"]["ptz"].tracked_objects) if len(self.trackers["license_plate"]["static"].tracked_objects) > 0:
self.print_objects_as_table(
self.trackers["license_plate"]["static"].tracked_objects
)
# Get tracked objects from type-specific trackers # Get tracked objects from type-specific trackers
for object_trackers in self.trackers.values(): for object_trackers in self.trackers.values():
@ -644,3 +659,20 @@ class NorfairTracker(ObjectTracker):
color=(255, 0, 0), color=(255, 0, 0),
thickness=None, thickness=None,
) )
if False:
# draw the current formatted time on the frame
from datetime import datetime
formatted_time = datetime.fromtimestamp(frame_time).strftime(
"%m/%d/%Y %I:%M:%S %p"
)
frame = Drawer.text(
frame,
formatted_time,
position=(10, 50),
size=1.5,
color=(255, 255, 255),
thickness=None,
)