LibreYOLO9P2s-visdrone: small-object aerial detector (research preview)
yolo9_p2 is a LibreYOLO model family: YOLOv9 with an added stride-4 (P2) detection scale. Stock YOLOv9 detects at strides 8/16/32; the P2 head adds a fourth scale at stride 4, so objects in the 4-16 px range land on a grid fine enough to be found. This checkpoint is the s size (7.2M params) trained on VisDrone2019-DET at 768 px.
Research preview. These weights are trained on VisDrone2019-DET, which is licensed CC BY-NC-SA 3.0, so they are for non-commercial use only and are not covered by LibreYOLO's permissive license. The checkpoint detects the 10 VisDrone aerial classes, not COCO.
Results (VisDrone2019-DET val, 548 images, pycocotools)
| model | AP | AP50 | AP_small | AP_med | AP_large |
|---|---|---|---|---|---|
| stock yolo9-t (control, 640) | 0.123 | 0.220 | 0.047 | 0.199 | 0.375 |
| yolo9_p2-t 640 (same-recipe A/B) | 0.138 | 0.254 | 0.070 | 0.213 | 0.352 |
| yolo9_p2-t 960 | 0.209 | 0.358 | 0.129 | 0.300 | 0.397 |
| yolo9_p2-s 768 (this model) | 0.226 | 0.385 | 0.141 | 0.324 | 0.484 |
In a controlled A/B (same recipe, resolution, and transfer init; the only difference was the P2 head), yolo9_p2-t beat stock yolo9-t by +49% AP_small, with the textbook size signature: large wins on small objects, slight loss on large ones. Across the project (P2 head + higher resolution + bigger size), small-object AP roughly doubled (0.070 → 0.141).
The full per-epoch metric history is in results.csv.
Honest scope notes
- Match the architecture to the arena. On COCO, the same architecture is worse than stock YOLOv9 (COCO "small" is 16-32 px, already covered by the stride-8 level). Use this for aerial/tiny-object imagery where objects fall below ~16 px; it is not a general-purpose detector.
- Not SOTA. Transformer-based small-object detectors (e.g. TinyFormer) reach higher AP on VisDrone at lower resolution. The value here is a simple, fast CNN that substantially improves its own small-object AP.
- Single seed. Every number is one training run; treat ±1 point as noise.
- Evaluate at 768. Train/test resolution mismatch tanks the numbers.
Usage
from libreyolo import LibreYOLO
model = LibreYOLO("LibreYOLO9P2s-visdrone.pt") # auto-downloads from this repo
results = model.predict("aerial.jpg", imgsz=768, conf=0.25)
results[0].show()
The yolo9_p2 family is merged on dev but not yet in a PyPI release. Until
it is, install LibreYOLO from source:
pip install git+https://github.com/LibreYOLO/libreyolo@dev.
Classes: pedestrian, people, bicycle, car, van, truck, tricycle, awning-tricycle, bus, motor.
Reproduce
- Download VisDrone2019-DET (train + val) from the official source (https://github.com/VisDrone/VisDrone-Dataset). The images are not redistributed here.
- Convert to YOLO layout with
build_visdrone.py(clean-room converter written from the public annotation spec). - Train with
train_visdrone.py, the exact recipe that produced this checkpoint (60 epochs, transfer init from stockLibreYOLO9s.pt, lr0=0.005, mosaic/mixup off, hsv+flip on, max_labels=600, imgsz=768, effective batch 16). Roughly 10 min/epoch on an RTX 5070 Ti.
Training notes that matter: the family default lr0=0.01 diverges on
transfer init; use 0.005. Mosaic hurts on VisDrone (tiling shrinks tiny
objects below detectability); keep it off.
Attribution
- Dataset: VisDrone2019-DET, AISKYEYE team, Lab of Machine Learning and Data Mining, Tianjin University, China (CC BY-NC-SA 3.0).
- Base architecture: YOLOv9 (MIT, MultimediaTechLab/YOLO); P2 extension by LibreYOLO.
- Transfer init: stock
LibreYOLO9s.pt(converted upstream YOLOv9-s weights).