helimistry/drone_detections
UAV Drone Detection and Tracking with YOLO and Kalman Filter Overview This project detects UAV drones in video using a deep learning object detector and tracks them across frames using a Kalman filter. The system processes every .mp4 file in a given input directory, saves frames containing detections, and produces one tracked output video per input video with bounding boxes and 2D trajectories overlaid. Test Videos The following YouTube videos were… See the full description on the dataset page: https://huggingface.co/datasets/helimistry/drone_detections.
UAV Drone Detection and Tracking with YOLO and Kalman Filter
Overview
This project detects UAV drones in video using a deep learning object detector and tracks them across frames using a Kalman filter. The system processes every .mp4 file in a given input directory, saves frames containing detections, and produces one tracked output video per input video with bounding boxes and 2D trajectories overlaid.
Test Videos
The following YouTube videos were used as the primary test inputs:
- Video 1: https://www.youtube.com/watch?v=DhmZ6W1UAv4
- Video 2: https://www.youtube.com/watch?v=YrydHPwRelI
Output Tracking Videos
Replace these with your uploaded YouTube links:
- Output Video 1: https://www.youtube.com/watch?v=hkxeuLE6Gns
- Output Video 2: https://www.youtube.com/watch?v=gO7WVP6hqQo
Dataset Choice
For drone detection, I used the Hugging Face dataset:
- Dataset:
ChinnaSAMY1/drone-detection-dataset - Source: Hugging Face
- Link https://huggingface.co/datasets/ChinnaSAMY1/drone-detection-dataset
This dataset was selected because it contains bounding box annotations for drones themselves, which matches the assignment requirement. Many aerial vision datasets instead focus on detecting objects from drones, which is not the same problem.
The dataset was converted into YOLO format for training. The original annotations were provided as bounding boxes, and each bounding box was transformed into normalized YOLO labels:
- class id
- center x
- center y
- width
- height
Since this project only tracks drones, the dataset was treated as a single-class detection task:
class 0 = drone
Detector Configuration
The detector used in this project is:
- Model: Ultralytics YOLOv8
- Starting checkpoint:
yolov8n.pt
YOLOv8 was chosen because it is easy to train, works well for custom object detection tasks, and integrates cleanly with Python for inference on video frames.
Training Setup
The detector was fine-tuned on the drone dataset after converting the dataset into YOLO folder structure.
Example configuration:
- image size:
640 - batch size:
16 - epochs:
30for a full run - smaller debug runs were also used, such as:
- epochs:
3 - image size:
416 - batch size:
8
The final trained model weights were saved as best.pt and then used during the video-processing stage.
Inference Pipeline
For each .mp4 file in the input directory:
- Open the video with OpenCV
- Read frames one by one
- Run the YOLO detector on each frame
- Keep detections above the confidence threshold
- Save any frame containing at least one detection into
detections/ - Pass the detections to the Kalman filter tracker
- Draw:
- bounding box
- track ID
- estimated center point
- 2D trajectory polyline
- Write the result to an output video
Kalman Filter Tracking
The second part of the project uses a Kalman filter to track the drone across frames.
State Design
The Kalman filter uses a constant velocity motion model with the following state vector:
[x, y, vx, vy]Noise Parameters
The Kalman filter requires covariance settings for uncertainty.
Initial covariance P
I used a large initial covariance: kf.P *= 500.0
This reflects high uncertainty at the beginning of the track, especially because the initial velocity is unknown.
Measurement noise R
I used: kf.R = np.array([ [25., 0.], [0., 25.] ])
This represents moderate uncertainty in detector measurements. Bounding box centers can jitter slightly from frame to frame, so the tracker should not trust every detection perfectly.
Process noise Q
I used:
q = 1.0 kf.Q = np.array([ [q, 0, 0, 0], [0, q, 0, 0], [0, 0, q, 0], [0, 0, 0, q] ])
This allows the tracker to adapt to small motion changes while still favoring smooth trajectories.
Handling Missing Detections
If no detection is assigned to a track in a frame, the Kalman filter still performs the predict step.
The track remains alive temporarily the predicted state is used for continuity. Each track keeps a missed counter.
If the tracker misses the drone for too many frames in a row, the track is removed.
