Skip to content

Repository files navigation

Drone Single Object Tracking — IR Pipeline

My father sent me a YouTube Shorts clip of a drone being tracked in real time and asked if I could do the same with his. I said sure, how hard could it be.

Harder than expected. A quadcopter doing aerobatics is roughly 10–30 px wide, moves fast enough to leave IoU at zero between frames, and blends into the background without preprocessing. What I thought would be a weekend script turned into a full tracking pipeline — morphological detection, Kalman filtering, YOLO fine-tuning, and a proper evaluation framework against annotated ground truth. The scope grew serious enough to become a portfolio project.

Three pipelines are compared: a classical CPU-only morphology + Kalman filter, a fine-tuned YOLOv8n + Kalman, and ByteTrack as a baseline. The key finding: IoU-based association fails catastrophically on fast small targets — switching to centroid distance recovers 2× the recall with the same detector.


Problem

Track a small quadcopter (~10–30 px) performing aerobatic maneuvers over 960 frames (32 s). The target is:

  • Small - often under 15 px, making IoU unreliable during fast motion
  • Fast - large frame-to-frame displacement breaks standard MOT association
  • Low contrast - requires morphological pre-processing to isolate the blob

Ground truth: 960-frame annotated clip in MOT format (annotation/quadcopter_chunk0/gt/gt.txt).


Pipelines

Pipeline A - IR Morphology + Kalman (CPU-only)

tracking_IR.py · detection_IR.py

New Top-Hat morphological transform isolates small bright blobs on a dark background. Detections feed a constant-velocity Kalman filter with a three-state machine: DETECTING → TRACKING → COASTING.

No GPU required. Designed for embedded deployment constraints.

python tracking_IR.py --mode display --tracker kalman
python tracking_IR.py --mode display --tracker particle   # SIR particle filter variant
python tracking_IR.py --mode config                        # live trackbar tuning
Argument Values Default
--mode display / config config
--tracker kalman / particle kalman
--video path to .mp4 quadcopter_aerobatics/chunk_00.mp4
--output path to .txt quadcopter_chunk0/predictions_IR.txt

config mode opens a live parameter panel (Dear PyGui) to tune detection and Kalman parameters interactively, alongside a 4-panel pipeline debug view. display mode loads config.json and runs clean.

Parameter What it controls
sigma_q (Process Noise) How much the Kalman trusts its motion model
sigma_r (Measurement Noise) How much it trusts the detector
assoc_dist Max centroid distance (px) to accept a detection as match
max_coast Frames to coast without a detection before dropping to DETECTING

Config mode

Display mode

Tracking in action (IR colormap, Kalman filter, 6 s clip):


Pipeline B - YOLOv8n + Kalman (best results)

kaggle_tracking_SOT.ipynb

YOLOv8n fine-tuned on Anti-UAV300 (18 k images, 50 epochs, Kaggle T4 GPU). Detections associated frame-to-frame using centroid distance rather than IoU.

Infrastructure note: Training was constrained to Kaggle's free T4 GPU tier (session time limits, no persistent storage). With access to the full Anti-UAV300 dataset, longer training runs, and proper augmentation pipelines, detection recall could realistically reach 0.95+. The current F1=0.887 reflects what is achievable under amateur infrastructure constraints, not the ceiling of the approach.


Pipeline C - ByteTrack (baseline)

kaggle_tracking_SOT.ipynb

Standard ByteTrack MOT pipeline using IoU association. Included as a baseline to quantify the failure mode of IoU on fast small targets.


Results

Evaluated on chunk_00.mp4 - 960 frames, 32 s. Metric: detection within 50 px of ground truth centroid.

Pipeline Recall Precision F1 Centroid err. ID sw.
IR morpho + Kalman (σ_q=50) 0.575 0.783 0.663 8.6 px 16
IR morpho + Kalman (σ_q=10) 0.688 0.807 0.742 8.5 px 11
Detection only (conf=0.1) 0.629 0.992 0.770 3.2 px x*
YOLO + centroid (conf=0.3) 0.686 0.997 0.813 5.2 px 12
YOLO + centroid (conf=0.1) 0.808 0.966 0.880 4.9 px 14
YOLO + centroid (conf=0.1, σ_q=3) 0.817 0.974 0.887 4.9 px 13
ByteTrack IoU (conf=0.1) 0.391 1.000 0.562 3.4 px 37#

* Detection-only has no temporal state; ID switches are not meaningful.

# ByteTrack ID switches counted as unique track IDs minus 1.

Full pipeline comparison - Top-Hat Morphology + Kalman vs YOLO + Kalman vs ByteTrack (960 frames, ground truth in green): (Click on the image bellow to access to a full demonstration video)

Why IoU fails here

ByteTrack's IoU association assumes the predicted and detected bounding boxes overlap between frames. On a fast small drone, frame-to-frame displacement routinely exceeds the box width; IoU collapses to zero and the tracker loses the target. Switching to centroid distance doubles recall (0.391 -> 0.817) with the same detector.


Failure analysis

Frames 700–960 see a recall drop in Pipeline A. Root cause: the drone scales down significantly as it flies away, falling below the morphological detector's minimum blob area. This is a detector sensitivity problem, not a Kalman tuning problem; the Kalman coasts correctly when detections drop, but can't recover once the blob is below threshold.


Evaluation

Predictions are exported in MOT format (one .txt per pipeline). Local evaluation against ground truth:

python metrics.py --pred quadcopter_chunk0/predictions_IR.txt \
                  --gt annotation/quadcopter_chunk0/gt/gt.txt

Metrics computed: Recall, Precision, F1, mean centroid error (threshold 50 px), ID switches.


Repository

.
├── tracking_IR.py          # Pipeline A — Top-Hat + Kalman/Particle filter
├── detection_IR.py         # New Top-Hat blob detector (standalone tuning)
├── hud.py                  # HUD overlay (FPS, state, centroid, trace)
├── metrics.py              # MOT evaluation — Recall / Precision / F1
├── config.json             # Tuned detection + Kalman parameters
├── show_vid.py             # Utility — display a video file
├── kaggle_tracking_SOT.ipynb  # Pipeline B+C — YOLO training + ByteTrack
└── annotation/
    └── quadcopter_chunk0/
        └── gt/gt.txt       # Ground truth (MOT format, 960 frames)

Video files (.mp4) and model weights (.pt) are not committed, they are too large. Download the test clip separately and place it at quadcopter_aerobatics/chunk_00.mp4.

About

My father asked if I could track his drone. I said sure. Three pipelines, R morphology + Kalman, fine-tuned YOLOv8n + Kalman, and ByteTrack, evaluated on a 960-frame aerobatics clip.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages