Detecting a car license plate (number plate) and then reading its text is a classic computer vision task called Automatic License Plate Recognition (ALPR / ANPR / LPR).
In 2025–2026 the most practical, accurate and widely used open-source approach in Python combines:
- Object detection → find the location of the plate in the image/video
- OCR (Optical Character Recognition) → read the characters from the cropped plate region
Modern Recommended Pipeline (2025–2026)
The current best open-source combo for most people is:
- Plate detection → YOLOv8 or YOLOv11 (Ultralytics)
- OCR → EasyOCR (very easy) or PaddleOCR (usually more accurate, especially on difficult plates)
Other strong options:
- YOLO + PaddleOCR (frequently wins in recent benchmarks for accuracy)
- YOLO + custom lightweight OCR models (e.g. fast-plate-ocr)
Step-by-step: How It Works
| Step | Task | Typical Tool/Library (2025–2026) | Why it's used |
|---|---|---|---|
| 1 | Capture image or video frame | OpenCV (cv2.VideoCapture or cv2.imread) | Read camera / file |
| 2 | (Optional) Detect vehicle first | YOLOv8 / YOLOv11 (pre-trained on COCO) | Helps when plates are small / far away |
| 3 | Detect license plate | Fine-tuned YOLOv8/YOLOv11 on plate dataset | Gives bounding box (x,y,w,h) |
| 4 | Crop the plate region | OpenCV slicing | Isolate only the plate |
| 5 | Pre-process crop (optional) | Grayscale, sharpen, threshold, deskew | Improve OCR accuracy |
| 6 | Read text (OCR) | EasyOCR or PaddleOCR | Extract letters & numbers |
| 7 | Post-process text | Regex, rules (remove spaces, fix common errors) | Clean up result (e.g. "O" → "0") |
| 8 | (Optional) Track across frames | SORT / ByteTrack / BoT-SORT | Stable reading on video |
Quick Start Code Example (YOLOv8 + EasyOCR)
This is one of the most popular and easiest setups right now.
# pip install ultralytics easyocr opencv-python
import cv2
from ultralytics import YOLO
import easyocr
import numpy as np
# 1. Load models
plate_model = YOLO("best.pt") # ← your fine-tuned plate detection model
reader = easyocr.Reader(['en'], gpu=True) # 'en' = English-like plates
# 2. Open video or image
cap = cv2.VideoCapture(0) # 0 = webcam or "video.mp4"
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 3. Detect plates
results = plate_model(frame, conf=0.5)
for result in results:
boxes = result.boxes.xyxy.cpu().numpy() # bounding boxes
for box in boxes:
x1, y1, x2, y2 = map(int, box[:4])
# 4. Crop plate
plate_crop = frame[y1:y2, x1:x2]
# 5. Optional pre-processing
gray = cv2.cvtColor(plate_crop, cv2.COLOR_BGR2GRAY)
# sharpen, threshold, etc. if needed
# 6. OCR
ocr_result = reader.readtext(gray)
if ocr_result:
text = ocr_result[0][-2].upper().replace(" ", "")
print("Plate:", text)
# Draw on frame
cv2.rectangle(frame, (x1,y1), (x2,y2), (0,255,0), 2)
cv2.putText(frame, text, (x1, y1-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,255,0), 2)
cv2.imshow("ANPR", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()Where to Get a Plate Detection Model
You almost never train from scratch today.
Popular ready-to-use / fine-tune options (2025–2026):
| Source | Model Type | Link / Dataset | Notes |
|---|---|---|---|
| Roboflow Universe | YOLOv8/YOLOv11 | https://universe.roboflow.com/search?q=license%20plate | Thousands of free plate datasets + export to YOLO format |
| Ultralytics community | YOLOv8 | Search GitHub "yolov8 license plate" | Many ready .pt files |
| computervisioneng | YOLOv8 | https://github.com/computervisioneng/automatic-number-plate-recognition-python-yolov8 | Very popular tutorial + model |
| Muhammad-Zeerak-Khan | YOLOv8 | https://github.com/Muhammad-Zeerak-Khan/Automatic-License-Plate-Recognition-using-YOLOv8 | Simple & good |
EasyOCR vs PaddleOCR – Quick Comparison (2025–2026)
| Feature | EasyOCR | PaddleOCR | Winner for most parking projects |
|---|---|---|---|
| Ease of use | Extremely easy (2–3 lines) | More setup, but still simple | EasyOCR |
| Accuracy (plates) | Good | Usually better (especially Arabic/ non-Latin) | PaddleOCR |
| Speed | Fast on CPU/GPU | Faster on GPU, good CPU fallback | PaddleOCR (GPU) |
| Languages | ~80 | 100+ (better multilingual) | PaddleOCR |
| GPU needed? | Optional | Much better with GPU | — |
→ For Egyptian / Arabic plates → try PaddleOCR first (better support for Arabic script).
Tips for Parked Cars (perpendicular to road)
- Use a slightly tilted downward camera (20–35°) → better view of front plates
- Crop tighter → helps OCR a lot
- Add pre-processing:Python
# Example sharpen + threshold kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]]) sharpened = cv2.filter2D(plate_crop, -1, kernel) thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
For PaddleOCR, you typically need a two-stage pipeline: one model to detect the plate (Detection) and another to read the characters (Recognition).
1. Basic Code for PaddleOCR
To get started, install the library and its dependencies:
pip install paddlepaddle-gpu # or paddlepaddle if no GPU
pip install paddleocr
Here is a simple inference script:
from paddleocr import PaddleOCR, draw_ocr
from PIL import Image
# Initialize PaddleOCR (lang='ar' for Arabic/Egyptian plates)
ocr = PaddleOCR(use_angle_cls=True, lang='ar')
img_path = 'egypt_plate.jpg'
result = ocr.ocr(img_path, cls=True)
# Print results
for idx in range(len(result)):
res = result[idx]
for line in res:
print(f"Text: {line[1][0]} | Confidence: {line[1][1]}")
# Optional: Visualize results
image = Image.open(img_path).convert('RGB')
boxes = [line[0] for line in result[0]]
txts = [line[1][0] for line in result[0]]
scores = [line[1][1] for line in result[0]]
im_show = draw_ocr(image, boxes, txts, scores, font_path='/path/to/arabic_font.ttf')
im_show = Image.fromarray(im_show)
im_show.save('result.jpg')
2. Egyptian Plate Datasets
Finding high-quality, annotated Egyptian data is the hardest part. Here are the best currently available resources:
EALPR (Egyptian Automatic License Plate Recognition): * Contains ~2,000+ images with 10,000+ annotated characters.
Covers 27 classes (Arabic letters and digits).
Where to find:
orDataset Ninja - EALPR .GitHub (ahmedramadan96/EALPR)
Kaggle - Egyptian Cars Plates:
There are multiple community uploads. Look for "Egyptian Car Plate Dataset with Annotated Bounding Boxes" by users like MahmoudKhater99 or alyalsayed.
Motorcycle Specific:
If you need motorcycle plates (which look different in Egypt), check the
on GitHub.telattar/Egyptian-motorcycle-license-plate-dataset
No comments:
Post a Comment