RF-DETR-Large β€” Dutch License Plate Detector

A single-class license-plate detector fine-tuned from roboflow/rf-detr-large on Dutch + synthetic plate data, exported to ONNX (fixed 768Γ—768 input).

  • Task: license-plate detection (one class: license_plate)
  • Base model: RF-DETR-Large (Apache 2.0)
  • Input: [1, 3, 768, 768] RGB, ImageNet-normalized
  • Outputs: dets (boxes, cx/cy/w/h normalized) and labels (per-query scores)
  • License: Apache 2.0

Live demo

Try it in the Space: Rickkosse/license-plate-detector (detection + fast-plate-ocr reading, with an "unreadable" gate for low-confidence plates).

Intended use & limitations

Detects Dutch-style plates well when they are reasonably large and frontal. Small, distant, or strongly angled plates in wide scenes are harder (a known data-coverage limitation). This is a prototype: training data was cc-by-nc / synthetic, so it is not a certified production model. For production, retrain on rights-clean, hand-verified data β€” the pipeline is unchanged.

Usage (ONNX Runtime)

import numpy as np, onnxruntime as ort
from PIL import Image

RES = 768
MEAN = np.array([0.485, 0.456, 0.406], np.float32)
STD  = np.array([0.229, 0.224, 0.225], np.float32)

sess = ort.InferenceSession("rfdetr-large.onnx", providers=ort.get_available_providers())
in_name = sess.get_inputs()[0].name

def detect(path, conf=0.5):
    pil = Image.open(path).convert("RGB")
    w0, h0 = pil.size
    img = pil.resize((RES, RES), Image.BILINEAR)
    x = (np.asarray(img, np.float32) / 255.0 - MEAN) / STD
    x = np.ascontiguousarray(x.transpose(2, 0, 1)[None], np.float32)
    dets, labels = sess.run(["dets", "labels"], {in_name: x})
    d = dets[0] if dets.ndim == 3 else dets
    l = labels[0] if labels.ndim == 3 else labels
    scores = l.max(axis=-1) if l.ndim > 1 else l
    if scores.max() > 1 or scores.min() < 0:
        scores = 1 / (1 + np.exp(-scores))          # logits -> prob
    out = []
    for (cx, cy, bw, bh), s in zip(d, scores):
        if s < conf:
            continue
        out.append((max(0,(cx-bw/2)*w0), max(0,(cy-bh/2)*h0),
                    min(w0,(cx+bw/2)*w0), min(h0,(cy+bh/2)*h0), float(s)))
    return out

print(detect("car.jpg"))   # [(x1, y1, x2, y2, score), ...] in pixels

Reading plates (optional, two-stage ALPR)

Pair detection with fast-plate-ocr (MIT): crop each detected box and read it. The OCR expects a grayscale crop with a channel axis (H, W, 1). See the Space app.py for a full example, including the confidence gate that flags unreadable plates instead of guessing.

Citation

Built on RF-DETR by Roboflow. OCR by fast-plate-ocr (ankandrew).

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support

Datasets used to train Rickkosse/rfdetr_licences_plate_detector

Space using Rickkosse/rfdetr_licences_plate_detector 1