|
from ultralytics import YOLO |
|
import gradio as gr |
|
from huggingface_hub import snapshot_download |
|
from PIL import Image, ImageDraw, ImageFont |
|
import cv2 |
|
import numpy as np |
|
hoppa = { |
|
"0": "٠", |
|
"1": "١", |
|
"2": "٢", |
|
"3": "٣", |
|
"4": "٤", |
|
"5": "٥", |
|
"6": "٦", |
|
"7": "٧", |
|
"8":"٨", |
|
"9":"٩", |
|
"Beh": "ب", |
|
"Daad": "ض", |
|
"Een": "ع", |
|
"F": "ف", |
|
"Heeh": "هه", |
|
"Kaaf": "ك", |
|
"Laam": "ل", |
|
"License Plate": "", |
|
"Meem": "م", |
|
"Noon": "ن", |
|
"Q": "ق", |
|
"R": "ر", |
|
"Saad": "ص", |
|
"Seen": "س", |
|
"Taa": "ط", |
|
"Wow": "و", |
|
"Yeeh": "ي", |
|
"Zah": "ظ", |
|
"Zeen": "ز", |
|
"alef": "أ", |
|
"car": "", |
|
"daal": "د", |
|
"geem": "ج", |
|
"ghayn": "غ", |
|
"khaa": "خ", |
|
"sheen": "ش", |
|
"teh": "ت", |
|
"theh": "ث", |
|
"zaal": "ذ", |
|
"7aah" : "ح" |
|
} |
|
|
|
|
|
model_dir = snapshot_download("omarelsayeed/licence_plates") + "/license_yolo8s_1024.pt" |
|
|
|
model = YOLO(model_dir) |
|
|
|
def predict_and_draw(img, conf_threshold, iou_threshold): |
|
""" |
|
Predict objects in an image, annotate with bounding boxes and markers, |
|
and generate a concatenated class string. |
|
""" |
|
|
|
image = np.array(img) |
|
|
|
|
|
results = model.predict(image, conf=conf_threshold, iou=iou_threshold, verbose=False ,imgsz=1024,) |
|
|
|
if not results: |
|
return img, "No objects detected." |
|
|
|
|
|
boxes_and_classes = [] |
|
for box, cls in zip(results[0].boxes.xyxy, results[0].boxes.cls): |
|
x_min, y_min, x_max, y_max = map(int, box[:4]) |
|
class_name = model.names[int(cls)] |
|
boxes_and_classes.append((x_max, y_min, class_name, (x_min, y_min, x_max, y_max))) |
|
|
|
|
|
boxes_and_classes.sort(key=lambda b: b[0], reverse=True) |
|
|
|
|
|
processed_classes = [] |
|
for _, _, cls, _ in boxes_and_classes: |
|
if cls.isalpha(): |
|
processed_classes.append(hoppa.get(cls, cls)) |
|
elif not cls.isdigit(): |
|
processed_classes.append(cls) |
|
else: |
|
processed_classes.append(cls) |
|
|
|
|
|
concatenated_classes = '-'.join([cls for cls in processed_classes if cls.isalpha()]) |
|
digits = ''.join([cls for cls in processed_classes if cls.isdigit()]) |
|
digits = ''.join([hoppa[str(c)] for c in digits]) |
|
digits = digits[::-1] |
|
if digits: |
|
concatenated_classes += f'-{digits}' if concatenated_classes else digits |
|
|
|
|
|
annotated_image = Image.fromarray(image) |
|
draw = ImageDraw.Draw(annotated_image) |
|
|
|
for _, _, _, (x_min, y_min, x_max, y_max) in boxes_and_classes: |
|
|
|
draw.rectangle([x_min, y_min, x_max, y_max], outline="green", width=2) |
|
|
|
draw.ellipse([x_max - 5, y_min - 5, x_max + 5, y_min + 5], fill="red") |
|
|
|
return annotated_image, concatenated_classes |
|
|
|
|
|
iface = gr.Interface( |
|
fn=predict_and_draw, |
|
inputs=[ |
|
gr.Image(type="pil", label="Upload Image"), |
|
gr.Slider(minimum=0, maximum=1, value=0.25, label="Confidence threshold"), |
|
gr.Slider(minimum=0, maximum=1, value=0.45, label="IoU threshold") |
|
], |
|
outputs=[ |
|
gr.Image(type="pil", label="Annotated Image"), |
|
gr.Textbox(label="Concatenated Classes") |
|
], |
|
title="License Plate Recognition.", |
|
description="Upload an image to detect license plates." |
|
) |
|
|
|
|
|
iface.launch() |
|
|