Víctor Sáez commited on
Commit
a7e9383
·
1 Parent(s): 4a473ee

Adding error catching

Browse files
Files changed (1) hide show
  1. app.py +176 -121
app.py CHANGED
@@ -4,6 +4,10 @@ from PIL import Image, ImageDraw, ImageFont
4
  from transformers import DetrImageProcessor, DetrForObjectDetection
5
  from pathlib import Path
6
  import transformers
 
 
 
 
7
 
8
  # Global variables to cache models
9
  current_model = None
@@ -38,14 +42,9 @@ def load_model(model_key):
38
  return current_model, current_processor
39
 
40
 
41
-
42
-
43
-
44
-
45
  # Load font
46
  font_path = Path("assets/fonts/arial.ttf")
47
  if not font_path.exists():
48
-
49
  print(f"Font file {font_path} not found. Using default font.")
50
  font = ImageFont.load_default()
51
  else:
@@ -62,6 +61,7 @@ translations = {
62
  "threshold_label": "Detection Threshold",
63
  "button": "Detect Objects",
64
  "info_label": "Detection Info",
 
65
  "model_fast": "General Objects (fast)",
66
  "model_precision": "General Objects (high precision)",
67
  "model_small": "Small Objects/Details (slow)",
@@ -76,6 +76,7 @@ translations = {
76
  "threshold_label": "Umbral de detección",
77
  "button": "Detectar objetos",
78
  "info_label": "Información de detección",
 
79
  "model_fast": "Objetos generales (rápido)",
80
  "model_precision": "Objetos generales (precisión alta)",
81
  "model_small": "Objetos pequeños/detalles (lento)",
@@ -90,6 +91,7 @@ translations = {
90
  "threshold_label": "Seuil de détection",
91
  "button": "Détecter les objets",
92
  "info_label": "Information de détection",
 
93
  "model_fast": "Objets généraux (rapide)",
94
  "model_precision": "Objets généraux (haute précision)",
95
  "model_small": "Petits objets/détails (lent)",
@@ -162,7 +164,6 @@ def get_helsinki_model(language_label):
162
  translation_cache = {}
163
 
164
 
165
-
166
  def translate_label(language_label, label):
167
  """Translates the given label to the target language."""
168
  # Check cache first
@@ -188,95 +189,102 @@ def translate_label(language_label, label):
188
 
189
  def detect_objects(image, language_selector, translated_model_selector, threshold):
190
  """Enhanced object detection with adjustable threshold and better info"""
191
- # Get the actual model key from the translated name
192
- model_selector = get_model_key_from_translation(translated_model_selector, language_selector)
193
-
194
- print(f"Processing image. Language: {language_selector}, Model: {model_selector}, Threshold: {threshold}")
195
-
196
- # Load the selected model
197
- model, processor = load_model(model_selector)
198
-
199
- # Process the image
200
- inputs = processor(images=image, return_tensors="pt")
201
- outputs = model(**inputs)
202
-
203
- # Convert model output to usable detection results with custom threshold
204
- target_sizes = torch.tensor([image.size[::-1]])
205
- results = processor.post_process_object_detection(
206
- outputs, threshold=threshold, target_sizes=target_sizes
207
- )[0]
208
-
209
- # Create a copy of the image for drawing
210
- image_with_boxes = image.copy()
211
- draw = ImageDraw.Draw(image_with_boxes)
212
-
213
- # Detection info
214
- detection_info = f"Detected {len(results['scores'])} objects with threshold {threshold}\n"
215
- detection_info += f"Model: {translated_model_selector} ({model_selector})\n\n"
216
-
217
- # Colors for different confidence levels
218
- colors = {
219
- 'high': 'red', # > 0.8
220
- 'medium': 'orange', # 0.5-0.8
221
- 'low': 'yellow' # < 0.5
222
- }
223
-
224
- detected_objects = []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
 
226
- for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
227
- confidence = score.item()
228
- box = [round(x, 2) for x in box.tolist()]
229
 
230
- # Choose color based on confidence
231
- if confidence > 0.8:
232
- color = colors['high']
233
- elif confidence > 0.5:
234
- color = colors['medium']
235
- else:
236
- color = colors['low']
237
-
238
- # Draw bounding box
239
- draw.rectangle(box, outline=color, width=3)
240
-
241
- # Prepare label text
242
- label_text = model.config.id2label[label.item()]
243
- translated_label = translate_label(language_selector, label_text)
244
- display_text = f"{translated_label}: {round(confidence, 3)}"
245
-
246
- # Store detection info
247
- detected_objects.append({
248
- 'label': label_text,
249
- 'translated': translated_label,
250
- 'confidence': confidence,
251
- 'box': box
252
- })
253
-
254
- # Calculate text position and size
255
- try:
256
- text_bbox = draw.textbbox((0, 0), display_text, font=font)
257
- text_width = text_bbox[2] - text_bbox[0]
258
- text_height = text_bbox[3] - text_bbox[1]
259
- except:
260
- # Fallback for older PIL versions
261
- text_width, text_height = draw.textsize(display_text, font=font)
262
-
263
- # Draw text background
264
- text_bg = [
265
- box[0], box[1] - text_height - 4,
266
- box[0] + text_width + 4, box[1]
267
- ]
268
- draw.rectangle(text_bg, fill="black")
269
- draw.text((box[0] + 2, box[1] - text_height - 2), display_text, fill="white", font=font)
270
-
271
- # Create detailed detection info
272
- if detected_objects:
273
- detection_info += "Objects found:\n"
274
- for obj in sorted(detected_objects, key=lambda x: x['confidence'], reverse=True):
275
- detection_info += f"- {obj['translated']} ({obj['label']}): {obj['confidence']:.3f}\n"
276
- else:
277
- detection_info += "No objects detected. Try lowering the threshold."
278
-
279
- return image_with_boxes, detection_info
280
 
281
 
282
  def build_app():
@@ -318,53 +326,100 @@ def build_app():
318
  max_lines=15
319
  )
320
 
 
 
 
 
 
 
 
 
 
 
321
  # Function to update interface when language changes
322
  def update_interface(selected_language):
323
- translated_choices = get_translated_model_choices(selected_language)
324
- default_model = t(selected_language, "model_fast")
325
-
326
- return [
327
- gr.update(value=t(selected_language, "title")),
328
- gr.update(label=t(selected_language, "dropdown_label")),
329
- gr.update(
330
- choices=translated_choices,
331
- value=default_model,
332
- label=t(selected_language, "dropdown_detection_model_label")
333
- ),
334
- gr.update(label=t(selected_language, "threshold_label")),
335
- gr.update(label=t(selected_language, "input_label")),
336
- gr.update(value=t(selected_language, "button")),
337
- gr.update(label=t(selected_language, "output_label")),
338
- gr.update(label=t(selected_language, "info_label"))
339
- ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
340
 
341
  # Connect language change event
342
  language_selector.change(
343
  fn=update_interface,
344
  inputs=language_selector,
345
  outputs=[title, language_selector, model_selector, threshold_slider,
346
- input_image, button, output_image, detection_info],
347
  queue=False
348
  )
349
 
350
  # Connect detection button click event
351
  button.click(
352
- fn=detect_objects,
353
  inputs=[input_image, language_selector, model_selector, threshold_slider],
354
- outputs=[output_image, detection_info]
355
  )
356
 
357
  return app
358
 
359
 
360
-
361
-
362
-
363
-
364
-
365
-
366
-
367
-
368
  # Initialize with default model
369
  load_model("DETR ResNet-50")
370
 
 
4
  from transformers import DetrImageProcessor, DetrForObjectDetection
5
  from pathlib import Path
6
  import transformers
7
+ import warnings
8
+ import traceback
9
+
10
+ warnings.filterwarnings("ignore", message=".*copying from a non-meta parameter.*")
11
 
12
  # Global variables to cache models
13
  current_model = None
 
42
  return current_model, current_processor
43
 
44
 
 
 
 
 
45
  # Load font
46
  font_path = Path("assets/fonts/arial.ttf")
47
  if not font_path.exists():
 
48
  print(f"Font file {font_path} not found. Using default font.")
49
  font = ImageFont.load_default()
50
  else:
 
61
  "threshold_label": "Detection Threshold",
62
  "button": "Detect Objects",
63
  "info_label": "Detection Info",
64
+ "error_label": "Error Messages",
65
  "model_fast": "General Objects (fast)",
66
  "model_precision": "General Objects (high precision)",
67
  "model_small": "Small Objects/Details (slow)",
 
76
  "threshold_label": "Umbral de detección",
77
  "button": "Detectar objetos",
78
  "info_label": "Información de detección",
79
+ "error_label": "Mensajes de error",
80
  "model_fast": "Objetos generales (rápido)",
81
  "model_precision": "Objetos generales (precisión alta)",
82
  "model_small": "Objetos pequeños/detalles (lento)",
 
91
  "threshold_label": "Seuil de détection",
92
  "button": "Détecter les objets",
93
  "info_label": "Information de détection",
94
+ "error_label": "Messages d'erreur",
95
  "model_fast": "Objets généraux (rapide)",
96
  "model_precision": "Objets généraux (haute précision)",
97
  "model_small": "Petits objets/détails (lent)",
 
164
  translation_cache = {}
165
 
166
 
 
167
  def translate_label(language_label, label):
168
  """Translates the given label to the target language."""
169
  # Check cache first
 
189
 
190
  def detect_objects(image, language_selector, translated_model_selector, threshold):
191
  """Enhanced object detection with adjustable threshold and better info"""
192
+ try:
193
+ # Get the actual model key from the translated name
194
+ model_selector = get_model_key_from_translation(translated_model_selector, language_selector)
195
+
196
+ print(f"Processing image. Language: {language_selector}, Model: {model_selector}, Threshold: {threshold}")
197
+
198
+ # Load the selected model
199
+ model, processor = load_model(model_selector)
200
+
201
+ # Process the image
202
+ inputs = processor(images=image, return_tensors="pt")
203
+ outputs = model(**inputs)
204
+
205
+ # Convert model output to usable detection results with custom threshold
206
+ target_sizes = torch.tensor([image.size[::-1]])
207
+ results = processor.post_process_object_detection(
208
+ outputs, threshold=threshold, target_sizes=target_sizes
209
+ )[0]
210
+
211
+ # Create a copy of the image for drawing
212
+ image_with_boxes = image.copy()
213
+ draw = ImageDraw.Draw(image_with_boxes)
214
+
215
+ # Detection info
216
+ detection_info = f"Detected {len(results['scores'])} objects with threshold {threshold}\n"
217
+ detection_info += f"Model: {translated_model_selector} ({model_selector})\n\n"
218
+
219
+ # Colors for different confidence levels
220
+ colors = {
221
+ 'high': 'red', # > 0.8
222
+ 'medium': 'orange', # 0.5-0.8
223
+ 'low': 'yellow' # < 0.5
224
+ }
225
+
226
+ detected_objects = []
227
+
228
+ for score, label, box in zip(results["scores"], results["labels"], results["boxes"]):
229
+ confidence = score.item()
230
+ box = [round(x, 2) for x in box.tolist()]
231
+
232
+ # Choose color based on confidence
233
+ if confidence > 0.8:
234
+ color = colors['high']
235
+ elif confidence > 0.5:
236
+ color = colors['medium']
237
+ else:
238
+ color = colors['low']
239
+
240
+ # Draw bounding box
241
+ draw.rectangle(box, outline=color, width=3)
242
+
243
+ # Prepare label text
244
+ label_text = model.config.id2label[label.item()]
245
+ translated_label = translate_label(language_selector, label_text)
246
+ display_text = f"{translated_label}: {round(confidence, 3)}"
247
+
248
+ # Store detection info
249
+ detected_objects.append({
250
+ 'label': label_text,
251
+ 'translated': translated_label,
252
+ 'confidence': confidence,
253
+ 'box': box
254
+ })
255
+
256
+ # Calculate text position and size
257
+ try:
258
+ text_bbox = draw.textbbox((0, 0), display_text, font=font)
259
+ text_width = text_bbox[2] - text_bbox[0]
260
+ text_height = text_bbox[3] - text_bbox[1]
261
+ except:
262
+ # Fallback for older PIL versions
263
+ text_width, text_height = draw.textsize(display_text, font=font)
264
+
265
+ # Draw text background
266
+ text_bg = [
267
+ box[0], box[1] - text_height - 4,
268
+ box[0] + text_width + 4, box[1]
269
+ ]
270
+ draw.rectangle(text_bg, fill="black")
271
+ draw.text((box[0] + 2, box[1] - text_height - 2), display_text, fill="white", font=font)
272
+
273
+ # Create detailed detection info
274
+ if detected_objects:
275
+ detection_info += "Objects found:\n"
276
+ for obj in sorted(detected_objects, key=lambda x: x['confidence'], reverse=True):
277
+ detection_info += f"- {obj['translated']} ({obj['label']}): {obj['confidence']:.3f}\n"
278
+ else:
279
+ detection_info += "No objects detected. Try lowering the threshold."
280
 
281
+ return image_with_boxes, detection_info, "" # Empty error message
 
 
282
 
283
+ except Exception as e:
284
+ error_message = f"Error in object detection:\n{str(e)}\n\nStack trace:\n{traceback.format_exc()}"
285
+ print(error_message)
286
+ # Return original image, error info, and error message
287
+ return image if image else None, "Detection failed. See error panel below.", error_message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
288
 
289
 
290
  def build_app():
 
326
  max_lines=15
327
  )
328
 
329
+ # Error panel - only visible when there are errors
330
+ with gr.Row():
331
+ error_panel = gr.Textbox(
332
+ label=t("English", "error_label"),
333
+ lines=8,
334
+ max_lines=20,
335
+ visible=False,
336
+ elem_classes=["error-panel"]
337
+ )
338
+
339
  # Function to update interface when language changes
340
  def update_interface(selected_language):
341
+ try:
342
+ translated_choices = get_translated_model_choices(selected_language)
343
+ default_model = t(selected_language, "model_fast")
344
+
345
+ return [
346
+ gr.update(value=t(selected_language, "title")),
347
+ gr.update(label=t(selected_language, "dropdown_label")),
348
+ gr.update(
349
+ choices=translated_choices,
350
+ value=default_model,
351
+ label=t(selected_language, "dropdown_detection_model_label")
352
+ ),
353
+ gr.update(label=t(selected_language, "threshold_label")),
354
+ gr.update(label=t(selected_language, "input_label")),
355
+ gr.update(value=t(selected_language, "button")),
356
+ gr.update(label=t(selected_language, "output_label")),
357
+ gr.update(label=t(selected_language, "info_label")),
358
+ gr.update(label=t(selected_language, "error_label"), value="", visible=False) # Clear errors
359
+ ]
360
+ except Exception as e:
361
+ error_message = f"Error updating interface language:\n{str(e)}\n\nStack trace:\n{traceback.format_exc()}"
362
+ print(error_message)
363
+
364
+ # Return safe defaults
365
+ return [
366
+ gr.update(), # Keep current title
367
+ gr.update(), # Keep current language selector
368
+ gr.update(), # Keep current model selector
369
+ gr.update(), # Keep current threshold
370
+ gr.update(), # Keep current input label
371
+ gr.update(), # Keep current button
372
+ gr.update(), # Keep current output label
373
+ gr.update(), # Keep current info label
374
+ gr.update(label="Error Messages", value=error_message, visible=True) # Show error
375
+ ]
376
+
377
+ # Enhanced detection function with error handling
378
+ def safe_detect_objects(image, language_selector, translated_model_selector, threshold):
379
+ if image is None:
380
+ return None, "Please upload an image first.", ""
381
+
382
+ try:
383
+ result_image, info, error = detect_objects(image, language_selector, translated_model_selector,
384
+ threshold)
385
+
386
+ # Update error panel visibility based on whether there's an error
387
+ error_visible = bool(error.strip())
388
+
389
+ return (
390
+ result_image,
391
+ info,
392
+ gr.update(value=error, visible=error_visible)
393
+ )
394
+
395
+ except Exception as e:
396
+ error_message = f"Unexpected error in detection:\n{str(e)}\n\nStack trace:\n{traceback.format_exc()}"
397
+ print(error_message)
398
+ return (
399
+ image, # Return original image
400
+ "Detection failed due to unexpected error. See error panel below.",
401
+ gr.update(value=error_message, visible=True)
402
+ )
403
 
404
  # Connect language change event
405
  language_selector.change(
406
  fn=update_interface,
407
  inputs=language_selector,
408
  outputs=[title, language_selector, model_selector, threshold_slider,
409
+ input_image, button, output_image, detection_info, error_panel],
410
  queue=False
411
  )
412
 
413
  # Connect detection button click event
414
  button.click(
415
+ fn=safe_detect_objects,
416
  inputs=[input_image, language_selector, model_selector, threshold_slider],
417
+ outputs=[output_image, detection_info, error_panel]
418
  )
419
 
420
  return app
421
 
422
 
 
 
 
 
 
 
 
 
423
  # Initialize with default model
424
  load_model("DETR ResNet-50")
425