YOLO OCR
Custom YOLO model trained to detect and recognize Arabic characters on Egyptian license plates.
Overview
Instead of traditional OCR engines, we use a YOLO object detection model where each Arabic character and numeral is a separate class. This approach is more robust for the specific format of Egyptian plates.
Architecture
The YOLO OCR model detects individual characters as objects:
Character Classes
Arabic Letters (17 classes)
| Character | Name | Character | Name |
|---|---|---|---|
| ا | Alef | ر | Ra |
| ب | Ba | س | Seen |
| ج | Jeem | ص | Sad |
| د | Dal | ط | Ta |
| ع | Ain | ف | Fa |
| ق | Qaf | ل | Lam |
| م | Meem | ن | Noon |
| ه | Ha | و | Waw |
| ي | Ya |
Numerals (10 classes)
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Usage
from src.pipeline.yolo_ocr import load_model, read_plate_text
# Load model
model = load_model("models/yolo11m_car_plate_ocr.pt")
# Read plate text
plate_crop = cv2.imread("plate.jpg")
text, confidence = read_plate_text(plate_crop, model=model)
print(f"Plate: {text} ({confidence:.1%})")
Character Assembly
Characters are sorted by their x-coordinate (left to right) and concatenated:
def read_plate_text(plate_crop, model, conf=0.25):
results = model.predict(plate_crop, conf=conf, verbose=False)
detections = []
for box in results[0].boxes:
cls_id = int(box.cls[0])
x_center = (box.xyxy[0][0] + box.xyxy[0][2]) / 2
char = CLASS_MAP.get(model.names[cls_id], model.names[cls_id])
detections.append((x_center, char, float(box.conf[0])))
# Sort by x position
detections.sort(key=lambda x: x[0])
# Build text
text = ''.join([d[1] for d in detections])
avg_conf = sum(d[2] for d in detections) / len(detections) if detections else 0
return text, avg_conf * 100
Class Mapping
The model outputs class names that need to be mapped to actual characters:
CLASS_MAP = {
"alef": "ا", "ba": "ب", "jeem": "ج", "dal": "د",
"ra": "ر", "seen": "س", "sad": "ص", "ta": "ط",
"ain": "ع", "fa": "ف", "qaf": "ق", "lam": "ل",
"meem": "م", "noon": "ن", "ha": "ه", "waw": "و",
"ya": "ي",
"zero": "0", "one": "1", "two": "2", "three": "3",
"four": "4", "five": "5", "six": "6", "seven": "7",
"eight": "8", "nine": "9"
}
Configuration
| Parameter | Default | Description |
|---|---|---|
conf |
0.25 | Detection confidence threshold |
iou |
0.45 | NMS IoU threshold |
verbose |
False | Print detection output |
Model File
Comparison with EasyOCR
| Feature | YOLO OCR | EasyOCR |
|---|---|---|
| Speed | ⚡ Faster | Slower |
| Arabic Accuracy | ✅ Higher (trained) | Lower (general) |
| Setup | Ultralytics | easyocr package |
| Customization | ✅ Trainable | Limited |
Training
The model was trained on Ultralytics HUB with:
- Dataset: Custom Egyptian plate character annotations
- Base Model: YOLOv11m
- Classes: 27 (17 Arabic letters + 10 numerals)
- Augmentation: Rotation, blur, brightness variation