edgefirst-tracker
Multi-object tracking for edge AI applications.
This crate provides object tracking algorithms for associating detections across video frames, enabling applications like counting, path analysis, and re-identification.
Algorithms
| Algorithm | Description | Use Case |
|---|---|---|
| ByteTrack | High-performance MOT with two-pass association and Kalman filtering | Real-time tracking |
Features
- UUID-based track IDs - Globally unique identifiers for each tracked object
- Kalman filtering - Smooth trajectory prediction and state estimation
- Two-pass association - High-confidence detections matched first, low-confidence detections used to recover lost tracks
- Configurable thresholds - Tunable IoU, confidence, and lifespan parameters
- Track lifecycle - Automatic creation, update, and expiry of tracks
Quick Start
use ;
// Build a tracker using the builder pattern
let mut tracker: = new
.track_high_conf // minimum confidence to create a new track
.track_iou // IoU threshold for matching
.track_update // Kalman filter update rate
.track_extra_lifespan // nanoseconds to keep a track alive without a match
.build;
// Process detections each frame
let detections: = get_detections_from_model;
let timestamp: u64 = frame_timestamp_ns;
let tracks: = tracker.update;
// Each detection gets associated track info (or None if untracked)
for in detections.iter.zip
// Query all currently active tracks
for active in tracker.get_active_tracks
Default Parameters
ByteTrackBuilder::new() sets the following defaults:
| Parameter | Default | Description |
|---|---|---|
track_high_conf |
0.7 |
Minimum score to create or match a high-confidence track |
track_iou |
0.25 |
IoU threshold for box association |
track_update |
0.25 |
Kalman filter update rate |
track_extra_lifespan |
500_000_000 ns |
How long a track survives without a matching detection |
Track Information
Tracker::update() returns Vec<Option<TrackInfo>>, one entry per input detection. Detections below the high-confidence threshold that do not match an existing track return None.
Each TrackInfo contains:
| Field | Type | Description |
|---|---|---|
uuid |
Uuid |
Globally unique track identifier |
tracked_location |
[f32; 4] |
Kalman-filtered bounding box in XYXY format [xmin, ymin, xmax, ymax] |
count |
i32 |
Number of times this track has been updated |
created |
u64 |
Timestamp (ns) when the track was first created |
last_updated |
u64 |
Timestamp (ns) of the last detection match |
Tracker::get_active_tracks() returns Vec<ActiveTrackInfo<T>>, which bundles TrackInfo with the raw last matched detection box:
| Field | Type | Description |
|---|---|---|
info |
TrackInfo |
Tracking metadata (see above) |
last_box |
T |
The last raw detection box before Kalman smoothing |
Implementing DetectionBox
Any type used with ByteTrack<T> must implement the DetectionBox trait:
use DetectionBox;
The bbox() method must return coordinates in XYXY format: [xmin, ymin, xmax, ymax] as normalized or pixel values consistent with the model output.
The Tracker Trait
Both ByteTrack<T> and any custom tracker must implement:
timestampis expected in nanoseconds and is used for track expiry calculations.- The returned
Vecfromupdateis aligned 1-to-1 with the inputboxesslice.
Integration with edgefirst-decoder
When used via edgefirst-hal or edgefirst-decoder, the tracker feature flag must be enabled:
[]
= { = "0.13", = ["tracker"] }
Or when depending on the decoder directly:
[]
= { = "0.13", = ["tracker"] }
The decoder exposes decode_tracked() which accepts any Tracker<DetectBox> implementation:
use ;
let mut tracker = new
.track_high_conf
.build;
decoder.decode_tracked?;
decode_tracked() populates:
output_boxes— decoded detection boxesoutput_masks— segmentation masks (empty if the model has no mask head)output_tracks—Vec<TrackInfo>with one entry per matched detection
License
Licensed under the Apache License, Version 2.0. See LICENSE for details.