wuhp commited on
Commit
0773a1d
Β·
verified Β·
1 Parent(s): 98068a0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -95
app.py CHANGED
@@ -6,15 +6,11 @@ from PIL import Image
6
  import shutil
7
  from ultralytics import YOLO
8
  import requests
9
- import zipfile
10
- import uuid
11
 
12
- # Constants
13
  MODELS_DIR = "models"
14
  MODELS_INFO_FILE = "models_info.json"
15
  TEMP_DIR = "temp"
16
  OUTPUT_DIR = "outputs"
17
- ZIP_DIR = "zips"
18
 
19
  def download_file(url, dest_path):
20
  """
@@ -29,7 +25,7 @@ def download_file(url, dest_path):
29
  """
30
  try:
31
  response = requests.get(url, stream=True)
32
- response.raise_for_status() # Raise an error on bad status
33
  with open(dest_path, 'wb') as f:
34
  for chunk in response.iter_content(chunk_size=8192):
35
  f.write(chunk)
@@ -60,19 +56,18 @@ def load_models(models_dir=MODELS_DIR, info_file=MODELS_INFO_FILE):
60
  display_name = model_info.get('display_name', model_name)
61
  model_dir = os.path.join(models_dir, model_name)
62
  os.makedirs(model_dir, exist_ok=True)
63
- model_path = os.path.join(model_dir, f"{model_name}.pt") # e.g., models/human/human.pt
64
  download_url = model_info['download_url']
65
 
66
- # Check if the model file exists
67
  if not os.path.isfile(model_path):
68
  print(f"Model '{display_name}' not found locally. Downloading from {download_url}...")
69
  success = download_file(download_url, model_path)
70
  if not success:
71
  print(f"Skipping model '{display_name}' due to download failure.")
72
- continue # Skip loading this model
73
 
74
  try:
75
- # Load the YOLO model
76
  model = YOLO(model_path)
77
  models[model_name] = {
78
  'display_name': display_name,
@@ -120,108 +115,103 @@ def get_model_info(model_info):
120
  )
121
  return info_text
122
 
123
- def zip_processed_images(processed_image_paths, model_name):
124
  """
125
- Create a ZIP file containing all processed images.
126
 
127
  Args:
128
- processed_image_paths (list): List of file paths to processed images.
129
- model_name (str): Name of the model used for processing.
 
 
130
 
131
  Returns:
132
- str: Path to the created ZIP file.
133
  """
134
- os.makedirs(ZIP_DIR, exist_ok=True)
135
- zip_filename = f"{model_name}_processed_images_{uuid.uuid4().hex}.zip"
136
- zip_path = os.path.join(ZIP_DIR, zip_filename)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
- with zipfile.ZipFile(zip_path, 'w') as zipf:
139
- for img_path in processed_image_paths:
140
- arcname = os.path.basename(img_path)
141
- zipf.write(img_path, arcname)
142
 
143
- print(f"Created ZIP file at {zip_path}.")
144
- return zip_path
145
 
146
- def predict_image(model_name, images, confidence, models):
 
 
 
 
 
 
147
  """
148
- Perform prediction on uploaded images using the selected YOLO model.
149
 
150
  Args:
151
  model_name (str): The name of the selected model.
152
- images (list): List of uploaded PIL.Image.Image objects.
153
  confidence (float): The confidence threshold for detections.
154
  models (dict): The dictionary containing models and their info.
155
 
156
  Returns:
157
- tuple: A status message, list of processed images, and a ZIP file for download.
158
  """
159
  model_entry = models.get(model_name, {})
160
  model = model_entry.get('model', None)
161
  if not model:
162
  return "Error: Model not found.", None, None
163
  try:
164
- # Ensure temporary and output directories exist
165
  os.makedirs(TEMP_DIR, exist_ok=True)
166
  os.makedirs(OUTPUT_DIR, exist_ok=True)
167
 
168
- processed_image_paths = []
169
- processed_images = []
170
-
171
- for idx, image in enumerate(images):
172
- # Generate unique filenames to avoid conflicts
173
- unique_id = uuid.uuid4().hex
174
- input_image_path = os.path.join(TEMP_DIR, f"{model_name}_input_image_{unique_id}.jpg")
175
- output_image_path = os.path.join(OUTPUT_DIR, f"{model_name}_output_image_{unique_id}.jpg")
176
-
177
- # Save the uploaded image to a temporary path
178
- image.save(input_image_path)
179
 
180
- # Perform prediction with user-specified confidence
181
- results = model(input_image_path, save=True, save_txt=False, conf=confidence)
182
 
183
- # Determine the output path
184
- # Ultralytics YOLO saves the results in 'runs/detect/predict' by default
185
- latest_run = sorted(Path("runs/detect").glob("predict*"), key=os.path.getmtime)[-1]
186
- detected_image_path = os.path.join(latest_run, Path(input_image_path).name)
187
 
188
- if not os.path.isfile(detected_image_path):
189
- # Alternative method to get the output path
190
- detected_image_path = results[0].save()[0]
191
 
192
- # Copy the output image to OUTPUT_DIR with a unique name
193
- shutil.copy(detected_image_path, output_image_path)
194
- processed_image_paths.append(output_image_path)
195
-
196
- # Open the processed image for display
197
- processed_image = Image.open(output_image_path)
198
- processed_images.append(processed_image)
199
-
200
- # Create a ZIP file containing all processed images
201
- zip_path = zip_processed_images(processed_image_paths, model_name)
202
-
203
- return "βœ… Prediction completed successfully.", processed_images, zip_path
204
 
 
205
  except Exception as e:
206
  return f"❌ Error during prediction: {str(e)}", None, None
207
 
208
  def main():
209
- # Load the models and their information
210
  models = load_models()
211
  if not models:
212
  print("No models loaded. Please check your models_info.json and model URLs.")
213
  return
214
 
215
- # Initialize Gradio Blocks interface
216
  with gr.Blocks() as demo:
217
  gr.Markdown("# πŸ§ͺ YOLOv11 Model Tester")
218
  gr.Markdown(
219
  """
220
- Upload one or multiple images to test different YOLOv11 models. Select a model from the dropdown to see its details.
221
  """
222
  )
223
 
224
- # Model selection and info
225
  with gr.Row():
226
  model_dropdown = gr.Dropdown(
227
  choices=[models[m]['display_name'] for m in models],
@@ -230,10 +220,8 @@ def main():
230
  )
231
  model_info = gr.Markdown("**Model Information will appear here.**")
232
 
233
- # Mapping from display_name to model_name
234
  display_to_name = {models[m]['display_name']: m for m in models}
235
 
236
- # Update model_info when a model is selected
237
  def update_model_info(selected_display_name):
238
  if not selected_display_name:
239
  return "Please select a model."
@@ -249,7 +237,6 @@ def main():
249
  outputs=model_info
250
  )
251
 
252
- # Confidence Threshold Slider
253
  with gr.Row():
254
  confidence_slider = gr.Slider(
255
  minimum=0.0,
@@ -260,33 +247,53 @@ def main():
260
  info="Adjust the minimum confidence required for detections to be displayed."
261
  )
262
 
263
- # Image Prediction Tab (now supporting multiple images)
264
- with gr.Tab("πŸ–ΌοΈ Image"):
265
- with gr.Column():
266
- image_input = gr.Images(
267
- label="Upload Images for Prediction",
268
- type='pil'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  )
270
- image_predict_btn = gr.Button("πŸ” Predict on Images")
271
- image_status = gr.Markdown("**Status will appear here.**")
272
- image_gallery = gr.Gallery(label="Predicted Images").style(grid=[2], height="auto")
273
- image_download_btn = gr.File(label="⬇️ Download All Processed Images (ZIP)")
274
-
275
- # Define the image prediction function
276
- def process_image(selected_display_name, images, confidence):
277
- if not selected_display_name:
278
- return "❌ Please select a model.", None, None
279
- if not images:
280
- return "❌ Please upload at least one image.", None, None
281
- model_name = display_to_name.get(selected_display_name)
282
- return predict_image(model_name, images, confidence, models)
283
-
284
- # Connect the predict button
285
- image_predict_btn.click(
286
- fn=process_image,
287
- inputs=[model_dropdown, image_input, confidence_slider],
288
- outputs=[image_status, image_gallery, image_download_btn]
289
- )
290
 
291
  gr.Markdown(
292
  """
@@ -295,8 +302,7 @@ def main():
295
  """
296
  )
297
 
298
- # Launch the Gradio app
299
  demo.launch()
300
 
301
  if __name__ == "__main__":
302
- main()
 
6
  import shutil
7
  from ultralytics import YOLO
8
  import requests
 
 
9
 
 
10
  MODELS_DIR = "models"
11
  MODELS_INFO_FILE = "models_info.json"
12
  TEMP_DIR = "temp"
13
  OUTPUT_DIR = "outputs"
 
14
 
15
  def download_file(url, dest_path):
16
  """
 
25
  """
26
  try:
27
  response = requests.get(url, stream=True)
28
+ response.raise_for_status()
29
  with open(dest_path, 'wb') as f:
30
  for chunk in response.iter_content(chunk_size=8192):
31
  f.write(chunk)
 
56
  display_name = model_info.get('display_name', model_name)
57
  model_dir = os.path.join(models_dir, model_name)
58
  os.makedirs(model_dir, exist_ok=True)
59
+ model_path = os.path.join(model_dir, f"{model_name}.pt")
60
  download_url = model_info['download_url']
61
 
 
62
  if not os.path.isfile(model_path):
63
  print(f"Model '{display_name}' not found locally. Downloading from {download_url}...")
64
  success = download_file(download_url, model_path)
65
  if not success:
66
  print(f"Skipping model '{display_name}' due to download failure.")
67
+ continue
68
 
69
  try:
70
+
71
  model = YOLO(model_path)
72
  models[model_name] = {
73
  'display_name': display_name,
 
115
  )
116
  return info_text
117
 
118
+ def predict_image(model_name, image, confidence, models):
119
  """
120
+ Perform prediction on an uploaded image using the selected YOLO model.
121
 
122
  Args:
123
+ model_name (str): The name of the selected model.
124
+ image (PIL.Image.Image): The uploaded image.
125
+ confidence (float): The confidence threshold for detections.
126
+ models (dict): The dictionary containing models and their info.
127
 
128
  Returns:
129
+ tuple: A status message, the processed image, and the path to the output image.
130
  """
131
+ model_entry = models.get(model_name, {})
132
+ model = model_entry.get('model', None)
133
+ if not model:
134
+ return "Error: Model not found.", None, None
135
+ try:
136
+
137
+ os.makedirs(TEMP_DIR, exist_ok=True)
138
+ os.makedirs(OUTPUT_DIR, exist_ok=True)
139
+
140
+ input_image_path = os.path.join(TEMP_DIR, f"{model_name}_input_image.jpg")
141
+ image.save(input_image_path)
142
+
143
+ results = model(input_image_path, save=True, save_txt=False, conf=confidence)
144
+
145
+ latest_run = sorted(Path("runs/detect").glob("predict*"), key=os.path.getmtime)[-1]
146
+ output_image_path = os.path.join(latest_run, Path(input_image_path).name)
147
+ if not os.path.isfile(output_image_path):
148
 
149
+ output_image_path = results[0].save()[0]
 
 
 
150
 
151
+ final_output_path = os.path.join(OUTPUT_DIR, f"{model_name}_output_image.jpg")
152
+ shutil.copy(output_image_path, final_output_path)
153
 
154
+ output_image = Image.open(final_output_path)
155
+
156
+ return "βœ… Prediction completed successfully.", output_image, final_output_path
157
+ except Exception as e:
158
+ return f"❌ Error during prediction: {str(e)}", None, None
159
+
160
+ def predict_video(model_name, video, confidence, models):
161
  """
162
+ Perform prediction on an uploaded video using the selected YOLO model.
163
 
164
  Args:
165
  model_name (str): The name of the selected model.
166
+ video (str): Path to the uploaded video file.
167
  confidence (float): The confidence threshold for detections.
168
  models (dict): The dictionary containing models and their info.
169
 
170
  Returns:
171
+ tuple: A status message, the processed video, and the path to the output video.
172
  """
173
  model_entry = models.get(model_name, {})
174
  model = model_entry.get('model', None)
175
  if not model:
176
  return "Error: Model not found.", None, None
177
  try:
178
+
179
  os.makedirs(TEMP_DIR, exist_ok=True)
180
  os.makedirs(OUTPUT_DIR, exist_ok=True)
181
 
182
+ input_video_path = os.path.join(TEMP_DIR, f"{model_name}_input_video.mp4")
183
+ shutil.copy(video, input_video_path)
 
 
 
 
 
 
 
 
 
184
 
185
+ results = model(input_video_path, save=True, save_txt=False, conf=confidence)
 
186
 
187
+ latest_run = sorted(Path("runs/detect").glob("predict*"), key=os.path.getmtime)[-1]
188
+ output_video_path = os.path.join(latest_run, Path(input_video_path).name)
189
+ if not os.path.isfile(output_video_path):
 
190
 
191
+ output_video_path = results[0].save()[0]
 
 
192
 
193
+ final_output_path = os.path.join(OUTPUT_DIR, f"{model_name}_output_video.mp4")
194
+ shutil.copy(output_video_path, final_output_path)
 
 
 
 
 
 
 
 
 
 
195
 
196
+ return "βœ… Prediction completed successfully.", final_output_path, final_output_path
197
  except Exception as e:
198
  return f"❌ Error during prediction: {str(e)}", None, None
199
 
200
  def main():
201
+
202
  models = load_models()
203
  if not models:
204
  print("No models loaded. Please check your models_info.json and model URLs.")
205
  return
206
 
 
207
  with gr.Blocks() as demo:
208
  gr.Markdown("# πŸ§ͺ YOLOv11 Model Tester")
209
  gr.Markdown(
210
  """
211
+ Upload images or videos to test different YOLOv11 models. Select a model from the dropdown to see its details.
212
  """
213
  )
214
 
 
215
  with gr.Row():
216
  model_dropdown = gr.Dropdown(
217
  choices=[models[m]['display_name'] for m in models],
 
220
  )
221
  model_info = gr.Markdown("**Model Information will appear here.**")
222
 
 
223
  display_to_name = {models[m]['display_name']: m for m in models}
224
 
 
225
  def update_model_info(selected_display_name):
226
  if not selected_display_name:
227
  return "Please select a model."
 
237
  outputs=model_info
238
  )
239
 
 
240
  with gr.Row():
241
  confidence_slider = gr.Slider(
242
  minimum=0.0,
 
247
  info="Adjust the minimum confidence required for detections to be displayed."
248
  )
249
 
250
+ with gr.Tabs():
251
+
252
+ with gr.Tab("πŸ–ΌοΈ Image"):
253
+ with gr.Column():
254
+ image_input = gr.Image(
255
+ type='pil',
256
+ label="Upload Image for Prediction"
257
+
258
+ )
259
+ image_predict_btn = gr.Button("πŸ” Predict on Image")
260
+ image_status = gr.Markdown("**Status will appear here.**")
261
+ image_output = gr.Image(label="Predicted Image")
262
+ image_download_btn = gr.File(label="⬇️ Download Predicted Image")
263
+
264
+ def process_image(selected_display_name, image, confidence):
265
+ if not selected_display_name:
266
+ return "❌ Please select a model.", None, None
267
+ model_name = display_to_name.get(selected_display_name)
268
+ return predict_image(model_name, image, confidence, models)
269
+
270
+ image_predict_btn.click(
271
+ fn=process_image,
272
+ inputs=[model_dropdown, image_input, confidence_slider],
273
+ outputs=[image_status, image_output, image_download_btn]
274
+ )
275
+
276
+ with gr.Tab("πŸŽ₯ Video"):
277
+ with gr.Column():
278
+ video_input = gr.Video(
279
+ label="Upload Video for Prediction"
280
+ )
281
+ video_predict_btn = gr.Button("πŸ” Predict on Video")
282
+ video_status = gr.Markdown("**Status will appear here.**")
283
+ video_output = gr.Video(label="Predicted Video")
284
+ video_download_btn = gr.File(label="⬇️ Download Predicted Video")
285
+
286
+ def process_video(selected_display_name, video, confidence):
287
+ if not selected_display_name:
288
+ return "❌ Please select a model.", None, None
289
+ model_name = display_to_name.get(selected_display_name)
290
+ return predict_video(model_name, video, confidence, models)
291
+
292
+ video_predict_btn.click(
293
+ fn=process_video,
294
+ inputs=[model_dropdown, video_input, confidence_slider],
295
+ outputs=[video_status, video_output, video_download_btn]
296
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
 
298
  gr.Markdown(
299
  """
 
302
  """
303
  )
304
 
 
305
  demo.launch()
306
 
307
  if __name__ == "__main__":
308
+ main()