A fine-tuned YOLOv8m-Pose model that detects vehicle license plates and precisely localizes their 4 corner keypoints (top-left, top-right, bottom-right, bottom-left). Designed for downstream tasks like logo replacement, plate anonymization, and perspective-corrected OCR.
Model Details
Property
Value
Base Model
YOLOv8m-Pose (Ultralytics)
Task
Object Detection + Keypoint Estimation
Classes
1 (Plate)
Keypoints
4 corners per plate (TL, TR, BR, BL)
Input Size
640 × 640 px
Model Size
~101 MB
Framework
PyTorch / Ultralytics
Performance Metrics
Evaluated on the held-out validation set (24 images):
Metric
Value
Box Precision
0.977
Box Recall
0.947
Box mAP@50
0.9875
Box mAP@50-95
0.8412
Pose Precision
0.934
Pose Recall
0.898
Pose mAP@50
0.9264
Pose mAP@50-95
0.9137
Model fully trained for all 150 epochs, achieving best-in-class performance at the final checkpoint.
Training Details
Parameter
Value
Epochs
150
Batch Size
16
Image Size
640 × 640
Optimizer
SGD (auto)
Learning Rate
0.01 → 0.01
Momentum
0.937
Weight Decay
0.0005
Pose Loss Weight
12.0
Keypoint Object Loss
2.0
Warmup Epochs
3
Augmentations
Mosaic, HSV, Flip-LR, Scale, Shear, Rotation
Device
CUDA GPU
Dataset
Source: Roboflow — license-plate-new dataset (v3)
License: CC BY 4.0
Train: 19000 images
Validation: 2400 images
Test: 2400 images
Annotation: YOLO Pose format, 4 keypoints per plate (x, y, visibility)
Quick Start
Installation
pip install ultralytics opencv-python numpy
Basic Inference
python
1from ultralytics import YOLO
2import cv2
34# Load model5model = YOLO("license_plate_keypoint.pt")67# Run inference on an image8results = model("car.jpg", conf=0.25)910for result in results:11if result.keypoints isnotNone:12for kpts in result.keypoints:13# kpts.xy shape: [4, 2] — (x, y) for each of the 4 corners14 corners = kpts.xy[0].cpu().numpy()15print("TL:", corners[0])16print("TR:", corners[1])17print("BR:", corners[2])18print("BL:", corners[3])
Using the Full Inference Pipeline
python
1from inference import LicensePlateKeypointDetector
23detector = LicensePlateKeypointDetector("license_plate_keypoint.pt")45# Detect keypoints only6result = detector.detect("car.jpg")7if result["success"]:8print("Keypoints:", result["keypoints"])9print("Confidence:", result["confidence"])1011# Detect and blur the plate12blurred = detector.blur_plate("car.jpg", output_path="blurred.jpg")1314# Detect and replace with a logo15replaced = detector.replace_logo("car.jpg","logo.png", output_path="out.jpg")
Batch Processing
python
1from inference import LicensePlateKeypointDetector
2from pathlib import Path
34detector = LicensePlateKeypointDetector("license_plate_keypoint.pt")56for img_path in Path("input_images").glob("*.jpg"):7 result = detector.detect(str(img_path))8if result["success"]:9print(f"{img_path.name}: {result['keypoints']}")