Abs6187 commited on
Commit
6715d1b
·
verified ·
1 Parent(s): 3f44134

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +138 -9
app.py CHANGED
@@ -7,6 +7,9 @@ import pandas as pd
7
  import os
8
  import cv2
9
  import time
 
 
 
10
 
11
  # Download sample images (optional)
12
  torch.hub.download_url_to_file('https://github.com/Janno1402/Helmet-License-Plate-Detection/blob/main/Sample-Image-1.jpg?raw=true', 'sample_1.jpg')
@@ -19,13 +22,86 @@ torch.hub.download_url_to_file('https://github.com/Janno1402/Helmet-License-Plat
19
  model = YOLO("best.pt")
20
  class_names = {0: 'With Helmet', 1: 'Without Helmet', 2: 'License Plate'}
21
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  def yoloV8_func(
23
  image=None,
24
  image_size=640,
25
  conf_threshold=0.4,
26
  iou_threshold=0.5,
27
  show_stats=True,
28
- show_confidence=True
 
29
  ):
30
  # Handle NoneType for image_size
31
  if image_size is None:
@@ -66,6 +142,23 @@ def yoloV8_func(
66
  "Dimensions": f"{int(x2-x1)}x{int(y2-y1)}"
67
  })
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  # Create stats text
70
  stats_text = ""
71
  if show_stats and detections:
@@ -74,6 +167,10 @@ def yoloV8_func(
74
  stats_text = "Detection Summary:\n"
75
  for obj, count in counts.items():
76
  stats_text += f"- {obj}: {count}\n"
 
 
 
 
77
 
78
  # Add stats to image if requested
79
  if show_stats and stats_text:
@@ -95,7 +192,7 @@ def yoloV8_func(
95
  # Create a detection table for display
96
  detection_table = pd.DataFrame(detections) if detections else pd.DataFrame(columns=["Object", "Confidence", "Position", "Dimensions"])
97
 
98
- return annotated_image, detection_table, stats_text
99
 
100
  # Define custom CSS for styling
101
  custom_css = """
@@ -107,15 +204,22 @@ custom_css = """
107
  color: #666;
108
  }
109
  .important { font-weight: bold; color: red; }
 
 
 
 
 
 
110
  """
111
 
112
  # Set up Gradio interface with Blocks for more control
113
  with gr.Blocks(css=custom_css, title="YOLOv11 Motorcyclist Helmet Detection") as demo:
114
- gr.HTML("<h1 id='title'>YOLOv11 Motorcyclist Helmet Detection</h1>")
115
  gr.HTML("""
116
  <div id='description'>
117
  <p>This application uses YOLOv11 to detect Motorcyclists with and without Helmets in images.</p>
118
  <p>Upload an image, adjust the parameters, and view the detection results with detailed statistics.</p>
 
119
  </div>
120
  """)
121
 
@@ -130,25 +234,49 @@ with gr.Blocks(css=custom_css, title="YOLOv11 Motorcyclist Helmet Detection") as
130
  iou_threshold = gr.Slider(minimum=0.0, maximum=1.0, value=0.5, step=0.05, label="IOU Threshold")
131
  show_stats = gr.Checkbox(value=True, label="Show Statistics on Image")
132
 
 
 
133
  submit_btn = gr.Button("Detect Objects", variant="primary")
134
  clear_btn = gr.Button("Clear")
135
 
136
  with gr.Column(scale=2):
137
  gr.Markdown("### Output Results")
138
- output_image = gr.Image(type="pil", label="Output Image")
139
  output_table = gr.Dataframe(
140
  headers=["Object", "Confidence", "Position", "Dimensions"],
141
  label="Detection Details",
142
  interactive=False
143
  )
144
  output_stats = gr.Textbox(label="Detection Summary", interactive=False)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
 
146
  # Examples
147
  gr.Markdown("### Example Images")
148
  gr.Examples(
149
  examples=[["sample_1.jpg"], ["sample_2.jpg"], ["sample_3.jpg"], ["sample_4.jpg"], ["sample_5.jpg"]],
150
  inputs=input_image,
151
- outputs=[output_image, output_table, output_stats],
152
  fn=yoloV8_func,
153
  cache_examples=True,
154
  )
@@ -158,20 +286,21 @@ with gr.Blocks(css=custom_css, title="YOLOv11 Motorcyclist Helmet Detection") as
158
  <div class='footer'>
159
  <p>Built with Gradio and Ultralytics YOLO</p>
160
  <p>Note: This is a demonstration application. Detection accuracy may vary based on image quality and conditions.</p>
 
161
  </div>
162
  """)
163
 
164
  # Button actions
165
  submit_btn.click(
166
  fn=yoloV8_func,
167
- inputs=[input_image, image_size, conf_threshold, iou_threshold, show_stats],
168
- outputs=[output_image, output_table, output_stats]
169
  )
170
 
171
  clear_btn.click(
172
- fn=lambda: [None, None, None],
173
  inputs=[],
174
- outputs=[input_image, output_image, output_table, output_stats]
175
  )
176
 
177
  if __name__ == "__main__":
 
7
  import os
8
  import cv2
9
  import time
10
+ import zipfile
11
+ import io
12
+ from datetime import datetime
13
 
14
  # Download sample images (optional)
15
  torch.hub.download_url_to_file('https://github.com/Janno1402/Helmet-License-Plate-Detection/blob/main/Sample-Image-1.jpg?raw=true', 'sample_1.jpg')
 
22
  model = YOLO("best.pt")
23
  class_names = {0: 'With Helmet', 1: 'Without Helmet', 2: 'License Plate'}
24
 
25
+ def crop_license_plates(image, detections):
26
+ """Crop license plates from the image based on detections"""
27
+ cropped_plates = []
28
+
29
+ if isinstance(image, str): # If image is a file path
30
+ image = Image.open(image)
31
+ elif isinstance(image, np.ndarray): # If image is numpy array
32
+ image = Image.fromarray(image)
33
+
34
+ for detection in detections:
35
+ if detection['Object'] == 'License Plate':
36
+ # Parse coordinates from position string
37
+ pos = detection['Position'].strip('()')
38
+ x1, y1 = map(int, pos.split(', '))
39
+
40
+ # Parse dimensions
41
+ dims = detection['Dimensions']
42
+ width, height = map(int, dims.split('x'))
43
+ x2, y2 = x1 + width, y1 + height
44
+
45
+ # Add some padding around the license plate
46
+ padding = 10
47
+ x1 = max(0, x1 - padding)
48
+ y1 = max(0, y1 - padding)
49
+ x2 = min(image.width, x2 + padding)
50
+ y2 = min(image.height, y2 + padding)
51
+
52
+ # Crop the license plate
53
+ cropped_plate = image.crop((x1, y1, x2, y2))
54
+ cropped_plates.append({
55
+ 'image': cropped_plate,
56
+ 'confidence': detection['Confidence'],
57
+ 'position': detection['Position']
58
+ })
59
+
60
+ return cropped_plates
61
+
62
+ def create_download_files(annotated_image, cropped_plates, detections):
63
+ """Create downloadable files including annotated image and cropped plates"""
64
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
65
+
66
+ # Create a temporary directory for files
67
+ os.makedirs("temp_downloads", exist_ok=True)
68
+
69
+ # Save annotated image
70
+ annotated_path = f"temp_downloads/annotated_image_{timestamp}.jpg"
71
+ annotated_image.save(annotated_path)
72
+
73
+ # Save cropped license plates
74
+ plate_paths = []
75
+ for i, plate_data in enumerate(cropped_plates):
76
+ plate_path = f"temp_downloads/license_plate_{i+1}_{timestamp}.jpg"
77
+ plate_data['image'].save(plate_path)
78
+ plate_paths.append(plate_path)
79
+
80
+ # Create detection report
81
+ report_path = f"temp_downloads/detection_report_{timestamp}.csv"
82
+ if detections:
83
+ df = pd.DataFrame(detections)
84
+ df.to_csv(report_path, index=False)
85
+
86
+ # Create zip file with all results
87
+ zip_path = f"temp_downloads/detection_results_{timestamp}.zip"
88
+ with zipfile.ZipFile(zip_path, 'w') as zipf:
89
+ zipf.write(annotated_path, f"annotated_image_{timestamp}.jpg")
90
+ for plate_path in plate_paths:
91
+ zipf.write(plate_path, os.path.basename(plate_path))
92
+ if os.path.exists(report_path):
93
+ zipf.write(report_path, f"detection_report_{timestamp}.csv")
94
+
95
+ return zip_path, annotated_path, plate_paths
96
+
97
  def yoloV8_func(
98
  image=None,
99
  image_size=640,
100
  conf_threshold=0.4,
101
  iou_threshold=0.5,
102
  show_stats=True,
103
+ show_confidence=True,
104
+ crop_plates=True
105
  ):
106
  # Handle NoneType for image_size
107
  if image_size is None:
 
142
  "Dimensions": f"{int(x2-x1)}x{int(y2-y1)}"
143
  })
144
 
145
+ # Crop license plates if requested
146
+ cropped_plates = []
147
+ license_plate_gallery = []
148
+ download_files = None
149
+
150
+ if crop_plates and detections:
151
+ cropped_plates = crop_license_plates(image, detections)
152
+ license_plate_gallery = [plate_data['image'] for plate_data in cropped_plates]
153
+
154
+ # Create download files
155
+ if cropped_plates or detections:
156
+ try:
157
+ download_files, _, _ = create_download_files(annotated_image, cropped_plates, detections)
158
+ except Exception as e:
159
+ print(f"Error creating download files: {e}")
160
+ download_files = None
161
+
162
  # Create stats text
163
  stats_text = ""
164
  if show_stats and detections:
 
167
  stats_text = "Detection Summary:\n"
168
  for obj, count in counts.items():
169
  stats_text += f"- {obj}: {count}\n"
170
+
171
+ # Add license plate info
172
+ if cropped_plates:
173
+ stats_text += f"\nLicense Plates Cropped: {len(cropped_plates)}\n"
174
 
175
  # Add stats to image if requested
176
  if show_stats and stats_text:
 
192
  # Create a detection table for display
193
  detection_table = pd.DataFrame(detections) if detections else pd.DataFrame(columns=["Object", "Confidence", "Position", "Dimensions"])
194
 
195
+ return annotated_image, detection_table, stats_text, license_plate_gallery, download_files
196
 
197
  # Define custom CSS for styling
198
  custom_css = """
 
204
  color: #666;
205
  }
206
  .important { font-weight: bold; color: red; }
207
+ .download-section {
208
+ background-color: #f0f0f0;
209
+ padding: 15px;
210
+ border-radius: 8px;
211
+ margin-top: 10px;
212
+ }
213
  """
214
 
215
  # Set up Gradio interface with Blocks for more control
216
  with gr.Blocks(css=custom_css, title="YOLOv11 Motorcyclist Helmet Detection") as demo:
217
+ gr.HTML("<h1 id='title'>YOLOv11 Motorcyclist Helmet Detection with License Plate Extraction</h1>")
218
  gr.HTML("""
219
  <div id='description'>
220
  <p>This application uses YOLOv11 to detect Motorcyclists with and without Helmets in images.</p>
221
  <p>Upload an image, adjust the parameters, and view the detection results with detailed statistics.</p>
222
+ <p><strong>New Features:</strong> License plate cropping and downloadable results!</p>
223
  </div>
224
  """)
225
 
 
234
  iou_threshold = gr.Slider(minimum=0.0, maximum=1.0, value=0.5, step=0.05, label="IOU Threshold")
235
  show_stats = gr.Checkbox(value=True, label="Show Statistics on Image")
236
 
237
+ crop_plates = gr.Checkbox(value=True, label="Crop License Plates")
238
+
239
  submit_btn = gr.Button("Detect Objects", variant="primary")
240
  clear_btn = gr.Button("Clear")
241
 
242
  with gr.Column(scale=2):
243
  gr.Markdown("### Output Results")
244
+ output_image = gr.Image(type="pil", label="Annotated Image")
245
  output_table = gr.Dataframe(
246
  headers=["Object", "Confidence", "Position", "Dimensions"],
247
  label="Detection Details",
248
  interactive=False
249
  )
250
  output_stats = gr.Textbox(label="Detection Summary", interactive=False)
251
+
252
+ # License plate gallery
253
+ gr.Markdown("### Cropped License Plates")
254
+ license_gallery = gr.Gallery(
255
+ label="Extracted License Plates",
256
+ show_label=True,
257
+ elem_id="license_gallery",
258
+ columns=3,
259
+ rows=2,
260
+ object_fit="contain",
261
+ height="auto"
262
+ )
263
+
264
+ # Download section
265
+ gr.Markdown("### Download Results")
266
+ with gr.Group(elem_classes="download-section"):
267
+ download_file = gr.File(
268
+ label="Download Complete Results (ZIP)",
269
+ interactive=False,
270
+ visible=True
271
+ )
272
+ gr.Markdown("*The ZIP file contains: annotated image, cropped license plates, and detection report (CSV)*")
273
 
274
  # Examples
275
  gr.Markdown("### Example Images")
276
  gr.Examples(
277
  examples=[["sample_1.jpg"], ["sample_2.jpg"], ["sample_3.jpg"], ["sample_4.jpg"], ["sample_5.jpg"]],
278
  inputs=input_image,
279
+ outputs=[output_image, output_table, output_stats, license_gallery, download_file],
280
  fn=yoloV8_func,
281
  cache_examples=True,
282
  )
 
286
  <div class='footer'>
287
  <p>Built with Gradio and Ultralytics YOLO</p>
288
  <p>Note: This is a demonstration application. Detection accuracy may vary based on image quality and conditions.</p>
289
+ <p><strong>License Plate Privacy:</strong> Extracted license plates are for demonstration purposes only.</p>
290
  </div>
291
  """)
292
 
293
  # Button actions
294
  submit_btn.click(
295
  fn=yoloV8_func,
296
+ inputs=[input_image, image_size, conf_threshold, iou_threshold, show_stats, gr.State(True), crop_plates],
297
+ outputs=[output_image, output_table, output_stats, license_gallery, download_file]
298
  )
299
 
300
  clear_btn.click(
301
+ fn=lambda: [None, None, None, None, None],
302
  inputs=[],
303
+ outputs=[input_image, output_image, output_table, output_stats, license_gallery, download_file]
304
  )
305
 
306
  if __name__ == "__main__":