makhresearch commited on
Commit
11f85a8
·
verified ·
1 Parent(s): b879b56

Initial commit of app.py for web-based license plate detection using Gradio

Browse files

🔍 Persian License Plate Detection - Web Interface (app.py)
This Python script provides a complete web-based interface for detecting Iranian vehicle license plates using a custom-trained YOLO model via Gradio.

✅ Key Features:
Model: YOLOv5-based (persian_license_plate_v1.pt) trained to detect Iranian license plates.

Frameworks used: Gradio (UI), Ultralytics YOLO, PyTorch, OpenCV.

Interface: Clean, user-friendly layout with drag-and-drop support and example image loading.

Automatic fallback: If the custom model is unavailable, a default YOLOv8n model is loaded to ensure the app still runs.

🧠 How It Works:
Image Upload: Users can upload an image of a car or choose from example images.

Model Inference: The script runs YOLO on the input image and detects license plates.

Bounding Box Drawing: A green box is drawn around each detected license plate, with the class label (license_plate) and confidence score.

Real-time Output: The processed image is shown alongside the original.

📁 Folder Structure:
persian_license_plate_v1.pt: Trained model file.

Persian_License_Plate_Images/: A folder containing example images used in the UI.

app.py: This main script running the Gradio app.

💡 Notes:
The model is trained specifically for Iranian license plates (green bounding box).

Best performance is achieved when the plate is clearly visible and well-lit.

Files changed (1) hide show
  1. app.py +145 -0
app.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ # این خط باید قبل از هرگونه import از torch یا ultralytics باشد
3
+ os.environ['PYTORCH_WEIGHTS_ONLY'] = 'false'
4
+
5
+ import gradio as gr
6
+ from ultralytics import YOLO
7
+ import cv2
8
+ import numpy as np
9
+ from PIL import Image
10
+
11
+ # --- 1. Load the Model ---
12
+ # توجه: نام مدل به چیزی که برای تشخیص پلاک آموزش داده‌اید تغییر کرده است.
13
+ # مطمئن شوید که فایل 'persian_license_plate_v1.pt' در کنار این اسکریپت وجود دارد.
14
+ try:
15
+ model = YOLO("persian_license_plate_v1.pt")
16
+ except Exception as e:
17
+ print(f"Error loading model: {e}")
18
+ # در صورت عدم وجود مدل، یک مدل پیش‌فرض یولو بارگذاری می‌شود تا برنامه اجرا شود
19
+ model = YOLO("yolov8n.pt")
20
+
21
+
22
+ # --- 2. Define Class Names ---
23
+ # برای این پروژه، ما فقط یک کلاس "پلاک خودرو" داریم.
24
+ class_names = ['license_plate']
25
+ # برای هر کلاس یک رنگ تعریف می‌کنیم (در اینجا فقط یک رنگ لازم است).
26
+ class_colors = [(0, 255, 0)] # رنگ سبز برای پلاک
27
+
28
+ # --- 3. Main Image Processing Function (Core logic unchanged) ---
29
+ def detect_license_plate(input_image: Image.Image):
30
+ """
31
+ This function takes an input image, detects a license plate,
32
+ draws a bounding box around it, and returns the result.
33
+ """
34
+ if input_image is None:
35
+ return None
36
+
37
+ # اجرای مدل روی تصویر ورودی
38
+ results = model(input_image, verbose=False)[0]
39
+
40
+ # تبدیل تصویر ورودی به فرمت مناسب برای پردازش با OpenCV
41
+ img_np = np.array(input_image.convert("RGB"))
42
+ img_copy = img_np.copy()
43
+
44
+ # بررسی اینکه آیا باکسی تشخیص داده شده است یا خیر
45
+ if results.boxes is not None:
46
+ boxes = results.boxes.data.cpu().numpy()
47
+
48
+ for box in boxes:
49
+ cls_id = int(box[5])
50
+ # اگر کلاس تشخیص داده شده در لیست کلاس‌های ما بود، آن را پردازش کن
51
+ if cls_id < len(class_names):
52
+ cls_name = class_names[cls_id]
53
+ color = class_colors[cls_id]
54
+
55
+ # استخراج مختصات کادر
56
+ x1, y1, x2, y2 = map(int, box[:4])
57
+
58
+ # رسم کادر دور پلاک
59
+ cv2.rectangle(img_copy, (x1, y1), (x2, y2), color, 3)
60
+
61
+ # آماده‌سازی و نوشتن لیبل (نام کلاس و امتیاز اطمینان)
62
+ label = f"{cls_name} {box[4]:.2f}"
63
+ cv2.putText(img_copy, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, color, 2)
64
+
65
+ return Image.fromarray(img_copy)
66
+
67
+ # --- 4. Dynamically Read Examples from a Folder ---
68
+ # نام فولدر به نامی مرتبط با پروژه تغییر کرده است.
69
+ examples_folder = "Persian_License_Plate_Images"
70
+ examples_list = []
71
+ try:
72
+ all_files_in_folder = os.listdir(examples_folder)
73
+ # فیلتر کردن فایل‌ها برای اطمینان از اینکه فقط تصاویر خوانده می‌شوند
74
+ image_extensions = ['.jpg', '.jpeg', '.png', '.bmp']
75
+ image_files = [f for f in all_files_in_folder if os.path.splitext(f)[1].lower() in image_extensions]
76
+ for filename in image_files:
77
+ full_path = os.path.join(examples_folder, filename)
78
+ examples_list.append(full_path)
79
+ except FileNotFoundError:
80
+ print(f"Warning: Folder '{examples_folder}' not found. No examples will be shown.")
81
+ except Exception as e:
82
+ print(f"An error occurred while reading examples: {e}")
83
+
84
+ # ===================================================================
85
+ # --- Key Section: Building the Custom Layout with gr.Blocks ---
86
+ # ===================================================================
87
+
88
+ # راهنمای متنی که برای پروژه تشخیص پلاک بازنویسی شده است.
89
+ guide_html = """
90
+ <hr>
91
+ <div style="text-align: center;">
92
+ <h3>🚗 Iranian License Plate Detection Guide 🇮🇷</h3>
93
+ <p>
94
+ This model is trained to detect and draw a box around <strong>standard Iranian vehicle license plates</strong>.
95
+ Upload your image, and the model will automatically identify the plate's location.
96
+ </p>
97
+ <div style="display: flex; justify-content: center; align-items: center; gap: 20px; margin-top: 15px;">
98
+ <div style="padding: 10px; border: 1px solid #4CAF50; border-radius: 8px; background-color: #f2fff2;">
99
+ <strong style="color: #005704;">🟩 License Plate</strong><br>
100
+ <em>
101
+ The green bounding box indicates the detected location of the license plate, along with the model's confidence score.
102
+ </em>
103
+ </div>
104
+ </div>
105
+ <br>
106
+ <p><strong>Note:</strong> For best results, use clear images where the license plate is easily readable.</p>
107
+ </div>
108
+ """
109
+
110
+ # شروع تعریف بلوک���های رابط کاربری
111
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="green")) as demo:
112
+ # ۱. عنوان اصلی و توضیحات اولیه
113
+ gr.Markdown("<h1 style='text-align: center;'>Persian License Plate Detection</h1>")
114
+ gr.Markdown(
115
+ "**Welcome!** Upload an image of a vehicle or click on one of the examples below. "
116
+ "The model will draw a green bounding box around the license plate and show the predicted class (`license_plate`)."
117
+ )
118
+
119
+ # ۲. چیدمان ورودی و خروجی در کنار هم
120
+ with gr.Row():
121
+ input_image = gr.Image(type="pil", label="Upload Vehicle Image")
122
+ output_image = gr.Image(type="pil", label="Processed Image with Detected Plate")
123
+
124
+ # ۳. دکمه برای ارسال تصویر
125
+ submit_btn = gr.Button("🔍 Detect License Plate")
126
+
127
+ # ۴. بخش نمونه‌ها
128
+ if examples_list:
129
+ gr.Examples(
130
+ examples=examples_list,
131
+ inputs=input_image,
132
+ outputs=output_image,
133
+ fn=detect_license_plate,
134
+ cache_examples=True,
135
+ )
136
+
137
+ # ۵. متن راهنمای کلاس‌ها که در پایین صفحه قرار می‌گیرد
138
+ gr.Markdown(guide_html)
139
+
140
+ # تعریف عملکرد دکمه: وقتی کلیک شد، تابع پردازش را با ورودی و خروجی مناسب اجرا کن
141
+ submit_btn.click(fn=detect_license_plate, inputs=input_image, outputs=output_image)
142
+
143
+ # اجرای برنامه
144
+ if __name__ == "__main__":
145
+ demo.launch(share=True)