makhresearch commited on
Commit
42de794
·
verified ·
1 Parent(s): 9432e72

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -50
app.py CHANGED
@@ -7,33 +7,51 @@ 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
 
@@ -41,30 +59,43 @@ def detect_license_plate(input_image: Image.Image):
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 = []
@@ -81,6 +112,7 @@ except FileNotFoundError:
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
  # ===================================================================
@@ -89,56 +121,52 @@ except Exception as e:
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__":
 
7
  import cv2
8
  import numpy as np
9
  from PIL import Image
10
+ import random
11
 
12
  # --- 1. Load the Model ---
13
+ # توجه: نام مدل به 'best.pt' برگردانده شد.
14
+ # مطمئن شوید که فایل 'best.pt' در کنار این اسکریپت وجود دارد.
15
  try:
16
+ model = YOLO("best.pt")
17
  except Exception as e:
18
  print(f"Error loading model: {e}")
19
  # در صورت عدم وجود مدل، یک مدل پیش‌فرض یولو بارگذاری می‌شود تا برنامه اجرا شود
20
  model = YOLO("yolov8n.pt")
21
 
22
 
23
+ # --- 2. Define Class Names & Character Map ---
24
+ # برای این پروژه، لیست کلاس‌ها تمام کاراکترهای ممکن را پوشش می‌دهد.
25
+ class_names = [
26
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
27
+ 'Alef', 'Be', 'Te', 'Se', 'Jim', 'Dal', 'Sin', 'Shin',
28
+ 'Sad', 'Ta', 'Za', 'Eyn', 'Ghaf', 'Lam', 'Mim', 'Nun',
29
+ 'He', 'Vav', 'Pe', 'Zhe', 'plate', 'Ye', 'Ze'
30
+ ]
31
 
32
+ # نقشه برای تبدیل ID کلاس به کاراکتر فارسی برای نمایش در خروجی متنی
33
+ char_map = {
34
+ 0: '۰', 1: '۱', 2: '۲', 3: '۳', 4: '۴', 5: '۵', 6: '۶', 7: '۷', 8: '۸', 9: '۹',
35
+ 10: 'الف', 11: 'ب', 12: 'ت', 13: 'ث', 14: 'ج', 15: 'د', 16: 'س', 17: 'ش',
36
+ 18: 'ص', 19: 'ط', 20: 'ظ', 21: 'ع', 22: 'ق', 23: 'ل', 24: 'م', 25: 'ن',
37
+ 26: 'ه', 27: 'و', 28: 'پ', 29: 'ژ', 31: 'ی', 32: 'ز'
38
+ # کلاس 30 (plate) از این نقشه حذف شده زیرا یک کاراکتر نیست.
39
+ }
40
+
41
+ # برای هر کلاس یک رنگ رندوم تعریف می‌کنیم.
42
+ class_colors = [[random.randint(0, 255) for _ in range(3)] for _ in range(len(class_names))]
43
+
44
+
45
+ # --- 3. Main Image Processing Function ---
46
+ def detect_and_read_plate(input_image: Image.Image):
47
  """
48
+ This function takes an input image, detects all objects (plate and characters),
49
+ draws bounding boxes, sorts the characters, and returns the processed image
50
+ along with the recognized license plate text.
51
  """
52
  if input_image is None:
53
+ return None, ""
54
+
55
  # اجرای مدل روی تصویر ورودی
56
  results = model(input_image, verbose=False)[0]
57
 
 
59
  img_np = np.array(input_image.convert("RGB"))
60
  img_copy = img_np.copy()
61
 
62
+ recognized_characters = []
63
+
64
  # بررسی اینکه آیا باکسی تشخیص داده شده است یا خیر
65
  if results.boxes is not None:
66
  boxes = results.boxes.data.cpu().numpy()
67
 
68
  for box in boxes:
69
+ x1, y1, x2, y2 = map(int, box[:4])
70
+ confidence = box[4]
71
  cls_id = int(box[5])
72
+
73
  if cls_id < len(class_names):
74
+ # گرفتن رنگ و لیبل برای رسم کادر
75
  color = class_colors[cls_id]
76
+ label = f"{class_names[cls_id]} {confidence:.2f}"
77
 
78
+ # رسم کادر دور هر شیء تشخیص داده شده
79
+ cv2.rectangle(img_copy, (x1, y1), (x2, y2), color, 2)
80
+ cv2.putText(img_copy, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
81
+
82
+ # اگر شیء تشخیص داده شده یک کاراکتر بود، آن را برای مرتب‌سازی ذخیره کن
83
+ if cls_id in char_map:
84
+ recognized_characters.append({'box': box, 'char': char_map[cls_id]})
85
+
86
+ # مرتب‌سازی کاراکترهای تشخیص داده شده بر اساس موقعیت افقی (x1)
87
+ plate_text = ""
88
+ if recognized_characters:
89
+ sorted_chars = sorted(recognized_characters, key=lambda item: item['box'][0])
90
+ # ساختن رشته نهایی پلاک
91
+ plate_text = " ".join([item['char'] for item in sorted_chars])
92
+ else:
93
+ plate_text = "No characters were detected."
94
 
95
+ return Image.fromarray(img_copy), plate_text
96
 
97
+
98
+ # --- 4. Dynamically Read Examples from a Folder (unchanged) ---
99
  # نام فولدر به نامی مرتبط با پروژه تغییر کرده است.
100
  examples_folder = "Persian_License_Plate_Images"
101
  examples_list = []
 
112
  except Exception as e:
113
  print(f"An error occurred while reading examples: {e}")
114
 
115
+
116
  # ===================================================================
117
  # --- Key Section: Building the Custom Layout with gr.Blocks ---
118
  # ===================================================================
 
121
  guide_html = """
122
  <hr>
123
  <div style="text-align: center;">
124
+ <h3>🚗 Iranian License Plate Detection & Reading Guide 🇮🇷</h3>
125
  <p>
126
+ This model detects <strong>Iranian vehicle license plates</strong> and reads the characters on them.
127
+ Upload an image, and the model will draw boxes around the plate and each character, then display the read text below.
128
  </p>
 
 
 
 
 
 
 
 
129
  <br>
130
  <p><strong>Note:</strong> For best results, use clear images where the license plate is easily readable.</p>
131
  </div>
132
  """
133
 
134
  # شروع تعریف بلوک‌های رابط کاربری
135
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as demo:
136
  # ۱. عنوان اصلی و توضیحات اولیه
137
+ gr.Markdown("<h1 style='text-align: center;'>Persian License Plate Detection and OCR</h1>")
138
  gr.Markdown(
139
+ "**Welcome!** Upload a vehicle image or click an example. "
140
+ "The model will draw bounding boxes and output the recognized plate text."
141
  )
142
 
143
+ # ۲. چیدمان ورودی و خروجی
144
  with gr.Row():
145
  input_image = gr.Image(type="pil", label="Upload Vehicle Image")
146
+ output_image = gr.Image(type="pil", label="Processed Image with Detections")
147
 
148
+ # کادر متنی برای نمایش پلاک خوانده شده
149
+ recognized_text = gr.Textbox(label="Recognized Plate Text", interactive=False)
150
+
151
  # ۳. دکمه برای ارسال تصویر
152
+ submit_btn = gr.Button("🔍 Detect and Read Plate")
153
 
154
  # ۴. بخش نمونه‌ها
155
  if examples_list:
156
  gr.Examples(
157
  examples=examples_list,
158
  inputs=input_image,
159
+ # خروجی‌ها شامل تصویر و کادر متنی هستند
160
+ outputs=[output_image, recognized_text],
161
+ fn=detect_and_read_plate,
162
  cache_examples=True,
163
  )
164
 
165
+ # ۵. متن راهنما
166
  gr.Markdown(guide_html)
167
 
168
+ # تعریف عملکرد دکمه: خروجی‌ها به تصویر و کادر متنی ارسال می‌شوند
169
+ submit_btn.click(fn=detect_and_read_plate, inputs=input_image, outputs=[output_image, recognized_text])
170
 
171
  # اجرای برنامه
172
  if __name__ == "__main__":