norfair-rs
Real-time multi-object tracking for Rust
Disclaimer: This is an unofficial Rust port of Python's norfair object tracking library. This project is NOT affiliated with, endorsed by, or associated with Tryolabs or the original norfair development team. All credit for the original design and algorithms goes to the original norfair authors.
Overview
norfair-rs is a Rust implementation of the norfair multi-object tracking library, bringing real-time object tracking capabilities to Rust applications with:
- Detector-agnostic design: Works with any object detector (YOLO, Faster R-CNN, custom models)
- Rust-native performance: Zero-cost abstractions, no GC, maximum speed
- Type-safe API: Compile-time validation of tracking configurations
- Comprehensive Tests: 289+ Rust tests + 98 Python tests ensuring correctness and equivalence with the original norfair library
- Drop-In-Replacement: Python bindings with
uv add norfair_rsandimport norfair_rs as norfair
Related Projects
- norfair - Original Python implementation by Tryolabs
- norfair-go - Go port of norfair (sibling project)
Features
- Flexible Distance Functions: IoU, Euclidean, Manhattan, Frobenius, Keypoint Voting, and more
- Multiple Filtering Options: Optimized Kalman filter, full filterpy-equivalent Kalman, or no filtering
- Re-identification (ReID): Full support for object re-identification with
reid_hit_counterlifecycle - Thread-safe: Concurrent-safe ID generation and tracking
- Python Callable Support: Use custom Python distance functions directly with the Tracker
Benchmarks
Cross-language performance comparison (IoU distance, OptimizedKalmanFilter):
| Scenario | Frames | Detections | norfair | norfair-go | norfair-rs (python) | norfair-rs (rust) |
|---|---|---|---|---|---|---|
| Small | 100 | 446 | 4,700 fps | 243,000 fps | 107,000 fps | 296,000 fps |
| Medium | 500 | 9,015 | 540 fps | 31,000 fps | 27,000 fps | 89,000 fps |
| Large | 1,000 | 44,996 | 101 fps | 3,800 fps | 11,000 fps | 41,000 fps |
| Stress | 2,000 | 179,789 | — | 547 fps | 5,200 fps | 18,500 fps |
Speedup norfair-rs (rust) vs norfair: 60-180x depending on scenario complexity Speedup norfair-rs (python) vs norfair: 20-50x (drop-in replacement)
Benchmarks run on Apple M3 Pro. See examples/benchmark/ for reproduction scripts.
Comparison
Play around with the norfair (python) vs norfair-rs (rust) comparison tool using:
Installation
Rust
Add to your Cargo.toml:
[]
= "0.3"
Python (Drop-in Replacement)
norfair-rs provides Python bindings that work as a drop-in replacement for the original norfair library, with 20-50x better performance:
# or: pip install norfair-rs
Then simply change your import:
# Before (original norfair)
# After (norfair-rs - same API, much faster!)
Most of your existing norfair code should work unchanged. See the benchmark results for performance comparisons.
Compatible with norfair:
- ✅
Detection,TrackedObject,Tracker- Same API - ✅ Custom Python callable distance functions
- ✅ Custom Python callable
reid_distance_function - ✅
create_keypoints_voting_distance(),create_normalized_mean_euclidean_distance() - ✅ All built-in distance functions via
get_distance_by_name() - ✅ Full ReID support with
reid_hit_counterlifecycle - ✅ Filter factories:
OptimizedKalmanFilterFactory,FilterPyKalmanFilterFactory,NoFilterFactory - ✅
TranslationTransformationfor camera motion
Not yet implemented: The following features from Python norfair are not available in norfair-rs:
- Video I/O -
Videoclass (requires OpenCV) - Drawing -
draw_boxes(),draw_points(),draw_tracked_objects(),Drawer,Paths(requires OpenCV) - Homography -
HomographyTransformation,MotionEstimator(requires OpenCV) - Utilities -
FixedCamera,get_cutout(),print_objects_as_table() - Scipy - Scipy vectorised distance functions and some other features.
Most of these features require OpenCV bindings which are not yet implemented. Core tracking works fully.
Quick Start (Rust)
use ;
Here's how the same tracking workflow looks in the original Python norfair library:
Python:
# OLD: from norfair import Detection, Tracker
# Create tracker
=
# Process frames
# Get detections from your detector
=
# Update tracker
=
# Use tracked objects
Key Differences:
- Rust: Explicit configuration structs vs Python kwargs
- Rust: Error handling with
Result<T, E>returns - Rust: Uses
nalgebramatrices instead of numpy arrays - Rust: Zero-cost abstractions with compile-time guarantees
Both implementations provide the same core functionality with Rust offering better performance.
Configuration Options
use ;
use distance_by_name;
let mut config = new;
// Tracking behavior
config.hit_counter_max = 15; // Frames to keep tracking without detection
config.initialization_delay = 3; // Detections required to initialize
config.pointwise_hit_counter_max = 4; // Per-point tracking threshold
config.detection_threshold = 0.5; // Minimum detection confidence
config.past_detections_length = 4; // History for re-identification
// Re-identification (optional)
config.reid_distance_function = Some;
config.reid_distance_threshold = 100.0;
config.reid_hit_counter_max = Some;
// Kalman filter
config.filter_factory = Boxnew;
Distance Functions
Built-in distance functions available via distance_by_name():
| Name | Description | Use Case |
|---|---|---|
"euclidean" |
L2 distance between points | Single-point tracking |
"iou" |
1 - Intersection over Union | Bounding box tracking |
"mean_euclidean" |
Average L2 across all points | Multi-keypoint tracking |
"mean_manhattan" |
Average L1 across all points | Grid-aligned tracking |
"frobenius" |
Frobenius norm of difference | Matrix comparison |
Custom distance functions can be implemented via the Distance trait.
Filter Options
Three filter types are available:
use ;
API Documentation
Core Types
Tracker- Main tracking engine that maintains object identities across framesDetection- Input from object detector (bounding boxes, keypoints, or arbitrary points)TrackedObject- Output object with stable ID, position estimate, and tracking metadataTrackerConfig- Configuration for tracker behaviorTrackedObjectFactory- Thread-safe ID generation
Camera Motion
use TranslationTransformation;
// Compensate for camera movement
let transform = new;
let tracked = tracker.update;
Feature Flags
[]
= { = "...", = ["opencv"] }
| Feature | Description |
|---|---|
opencv |
Enable video I/O, drawing, and homography transforms |
License & Attribution
norfair-rs is licensed under the BSD 3-Clause License.
This Rust port is based on the original norfair by Tryolabs (BSD 3-Clause). Their well-designed, detector-agnostic architecture made this port possible. Internal modules include code adapted from several Python libraries—see THIRD_PARTY_LICENSES.md for complete attribution.
Citation: If using this library in research, please cite the original norfair paper as described here.
Contributing: Issues and pull requests welcome!