Skip to content

Feature request: optional vehicle-detect + crop stage for small plates in high-resolution frames #46

Description

@maidmaid

Summary

Propose an optional "vehicle-first" stage: detect the vehicle with a lightweight COCO detector, crop a square around it, then run the existing plate detector + OCR on that crop. It recovers plates that are too small to detect once a high-resolution frame is resized to the 608px detector input. This is complementary to the tiling idea in #39, but uses one extra forward pass instead of N tiles, with no overlap/dedup bookkeeping.

Problem

fast-alpr resizes the whole frame to the detector input (e.g. 608×608) before plate detection, so on high-res frames a distant plate becomes too small to detect or read (same root cause as #39).

Concrete example — a 2560×1440 entrance camera: the plate is ~60px wide in the frame → ~14px after the resize to 608 → unreadable, even though it's perfectly legible at full resolution.

Why vehicle-crop (vs tiling)

The plate is too small to detect full-frame, but the vehicle is large (~600px) and detected trivially even after downscaling. So:

  1. one cheap COCO detector pass → largest vehicle box
  2. crop a square (~608px, matching the plate detector input) around it
  3. run the existing plate detector + OCR on the crop, mapping boxes back to full-frame coords

Versus tiling: 1 extra pass instead of 2×2/3×2 tiles, no overlap/dedup, and the crop is centered on the actual vehicle so the plate lands near native resolution.

Empirical result

On a 30s clip (2560×1440, two cars), exact-correct reads / total detections over the same frames, using yolo-v9-s-608 + european-plates-mobile-vit-v2:

input to plate detector exact / detections
full frame (downscaled to 608) 22 / 49
static crop ~1200px (downscaled) 102 / 173
square crop ~608px (native res) 80 / 110 — highest precision (72%)

A native-resolution crop centered on the vehicle gives the best precision; the remaining lever is centering it reliably, which a vehicle detector does per-frame.

Cost

Modern nano detectors make the extra stage cheap — e.g. YOLO26n (NMS-free, ONNX output [1,300,6]) or YOLOv8n, ~30–80ms on CPU. Detecting a large vehicle is an easy task, so even the nano tier is reliable (≈0.9 conf in my tests).

Possible API

alpr = ALPR(..., vehicle_model="yolo26n", vehicle_classes=(2, 3, 5, 7))
alpr.predict(img)  # internally: detect vehicle → crop → plate detect → map boxes back

or a standalone vehicle_crop_predict() helper, mirroring the sliced_predict() idea from #39.

Offer

Happy to open a PR if this aligns with the project's direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions