dashcam-perception

Fine-tuning YOLOv8 for dashcam perception on BDD100K — and building the evaluation framework to prove, class by class, that it worked.

GitHub repoPython · PyTorch · YOLOv8

The problem

A YOLOv8 model pretrained on COCO already knows car, person, and bus. But a dashcam has to read the road, and two of the classes that matter most — traffic sign and rider — have no COCO equivalent at all. The pretrained model scores exactly zero on them, not because it is bad, but because it was never taught they exist.

Traffic lights are worse than nothing: COCO has them, so the model is confident, but at driving distances it detects them poorly. A detector that misses signs and misreads lights is not much use on a road.

Approach

Fine-tune YOLOv8m on 70,000 BDD100K images across its 10-class detection set, then measure the gain honestly. The measurement was the harder half: I wrote an AP@0.5 evaluator from scratch — IoU matching, per-class precision/recall, VOC all-point interpolation — so the COCO baseline and the fine-tuned model are scored through identical code on the same images. The delta that produces is the claim I actually trust.

Results

0.350 → 0.524

+49.7% mAP@0.5 over the COCO baseline

The two classes COCO cannot see go from nothing to 0.66 and 0.36, and the largest gains land exactly where a dashcam needs them — signs, lights, and riders. Every class but one improves.

COCO baselineFine-tuned
traffic sign
traffic light
rider
truck
car
bus
bicycle
person
motorcycle
train
0.00.20.40.60.8
AP@0.5
ClassBaselineFine-tunedΔInstances
traffic sign0.0000.660+0.6601,873
traffic light0.2390.628+0.3891,339
rider †0.0000.358+0.35837
truck0.4580.631+0.173207
car0.6120.781+0.1695,300
bus0.4880.651+0.16384
bicycle †0.2920.417+0.12557
person0.5160.627+0.111760
motorcycle †0.3950.491+0.09618
train †0.5000.000−0.5001
mAP@0.50.3500.524+0.174

† Low instance support — these APs carry wide error bars. train has a single instance in the subset, so its −0.500 is one missed box, not a real regression; excluding it, mAP@0.5 goes 0.333 → 0.583.

Predictions vs. ground truth

Green is the ground truth, red is the fine-tuned model — including a case where it falls short.

Dense daytime intersection with ground-truth and predicted boxes side by side
A dense daytime intersection — 35 labelled objects, and the model recovers the cars, signs, and lights that a COCO detector would have left blank.
Night driving scene with ground-truth and predicted boxes side by side
Night, the hard case. It catches the lit signs and distant lights but misses the dark car on the left — the kind of failure low light actually produces.
Highway scene where the model misses several small distant objects
A failure case, included on purpose. Only ~37% of the labelled objects are found here; small and distant boxes are where the model still falls short.

Engineering notes

The evaluator is the point. Reading mAP off the trainer would have measured the fine-tuned model against itself. Writing the metric by hand meant the baseline and the fine-tune were graded the same way, which is the only reason the before/after is trustworthy.

Baseline remapping. To grade a COCO model against BDD labels at all, its predictions are mapped onto BDD's 10 classes and out-of-vocabulary detections dropped — otherwise the comparison would be apples to oranges.

Trained on an M-series Mac. Batch size and image resolution were tuned to fit unified-memory limits (batch 32, imgsz 416) rather than a datacenter GPU's headroom.

The bug that cost the most. An early run trained on silently mismatched image/label paths and learned nothing useful. Fixing the data plumbing — not the model — was what unlocked the result.