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

Adding error catching

Browse files
Files changed (1) hide show
  1. app.py +159 -74
app.py CHANGED
@@ -6,6 +6,7 @@ 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
 
@@ -14,9 +15,11 @@ current_model = None
14
  current_processor = None
15
  current_model_name = None
16
 
 
 
 
17
  # Available models with better selection
18
  available_models = {
19
- # DETR Models
20
  "DETR ResNet-50": "facebook/detr-resnet-50",
21
  "DETR ResNet-101": "facebook/detr-resnet-101",
22
  "DETR DC5": "facebook/detr-resnet-50-dc5",
@@ -26,18 +29,20 @@ available_models = {
26
 
27
  def load_model(model_key):
28
  """Load model and processor based on selected model key"""
29
- global current_model, current_processor, current_model_name
30
 
31
  model_name = available_models[model_key]
32
 
33
  # Only load if it's a different model
34
  if current_model_name != model_name:
 
35
  print(f"Loading model: {model_name}")
36
  current_processor = DetrImageProcessor.from_pretrained(model_name)
37
  current_model = DetrForObjectDetection.from_pretrained(model_name)
38
  current_model_name = model_name
39
  print(f"Model loaded: {model_name}")
40
  print(f"Available labels: {list(current_model.config.id2label.values())}")
 
41
 
42
  return current_model, current_processor
43
 
@@ -48,7 +53,7 @@ if not font_path.exists():
48
  print(f"Font file {font_path} not found. Using default font.")
49
  font = ImageFont.load_default()
50
  else:
51
- font = ImageFont.truetype(str(font_path), size=100) # Reduced font size
52
 
53
  # Set up translations for the app
54
  translations = {
@@ -62,6 +67,8 @@ translations = {
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)",
@@ -77,6 +84,8 @@ translations = {
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)",
@@ -92,6 +101,8 @@ translations = {
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)",
@@ -106,6 +117,9 @@ def t(language, key):
106
 
107
  def get_translated_model_choices(language):
108
  """Get model choices translated to the selected language"""
 
 
 
109
  model_mapping = {
110
  "DETR ResNet-50": "model_fast",
111
  "DETR ResNet-101": "model_precision",
@@ -119,9 +133,10 @@ def get_translated_model_choices(language):
119
  translation_key = model_mapping[model_key]
120
  translated_name = t(language, translation_key)
121
  else:
122
- translated_name = model_key # Fallback to original name
123
  translated_choices.append(translated_name)
124
 
 
125
  return translated_choices
126
 
127
 
@@ -160,7 +175,7 @@ def get_helsinki_model(language_label):
160
  return f"Helsinki-NLP/opus-mt-en-{target}"
161
 
162
 
163
- # add cache for translations
164
  translation_cache = {}
165
 
166
 
@@ -189,26 +204,36 @@ def translate_label(language_label, label):
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
 
@@ -278,15 +303,118 @@ def detect_objects(image, language_selector, translated_model_selector, threshol
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():
291
  with gr.Blocks(theme=gr.themes.Soft()) as app:
292
  with gr.Row():
@@ -302,14 +430,14 @@ def build_app():
302
  with gr.Column(scale=1):
303
  model_selector = gr.Dropdown(
304
  choices=get_translated_model_choices("English"),
305
- value=t("English", "model_fast"), # Default to translated "fast" option
306
  label=t("English", "dropdown_detection_model_label")
307
  )
308
  with gr.Column(scale=1):
309
  threshold_slider = gr.Slider(
310
  minimum=0.1,
311
  maximum=0.95,
312
- value=0.5, # Lowered default threshold
313
  step=0.05,
314
  label=t("English", "threshold_label")
315
  )
@@ -336,77 +464,25 @@ def build_app():
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
 
@@ -417,11 +493,20 @@ def build_app():
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
 
426
  # Launch the application
427
  if __name__ == "__main__":
 
6
  import transformers
7
  import warnings
8
  import traceback
9
+ import datetime
10
 
11
  warnings.filterwarnings("ignore", message=".*copying from a non-meta parameter.*")
12
 
 
15
  current_processor = None
16
  current_model_name = None
17
 
18
+ # Global debug state
19
+ debug_info = {"last_error": "", "step": "", "language": "", "timestamp": ""}
20
+
21
  # Available models with better selection
22
  available_models = {
 
23
  "DETR ResNet-50": "facebook/detr-resnet-50",
24
  "DETR ResNet-101": "facebook/detr-resnet-101",
25
  "DETR DC5": "facebook/detr-resnet-50-dc5",
 
29
 
30
  def load_model(model_key):
31
  """Load model and processor based on selected model key"""
32
+ global current_model, current_processor, current_model_name, debug_info
33
 
34
  model_name = available_models[model_key]
35
 
36
  # Only load if it's a different model
37
  if current_model_name != model_name:
38
+ debug_info["step"] = f"Loading model: {model_name}"
39
  print(f"Loading model: {model_name}")
40
  current_processor = DetrImageProcessor.from_pretrained(model_name)
41
  current_model = DetrForObjectDetection.from_pretrained(model_name)
42
  current_model_name = model_name
43
  print(f"Model loaded: {model_name}")
44
  print(f"Available labels: {list(current_model.config.id2label.values())}")
45
+ debug_info["step"] = f"Model loaded successfully: {model_name}"
46
 
47
  return current_model, current_processor
48
 
 
53
  print(f"Font file {font_path} not found. Using default font.")
54
  font = ImageFont.load_default()
55
  else:
56
+ font = ImageFont.truetype(str(font_path), size=100)
57
 
58
  # Set up translations for the app
59
  translations = {
 
67
  "button": "Detect Objects",
68
  "info_label": "Detection Info",
69
  "error_label": "Error Messages",
70
+ "debug_label": "Debug Status",
71
+ "debug_button": "Show Debug Status",
72
  "model_fast": "General Objects (fast)",
73
  "model_precision": "General Objects (high precision)",
74
  "model_small": "Small Objects/Details (slow)",
 
84
  "button": "Detectar objetos",
85
  "info_label": "Información de detección",
86
  "error_label": "Mensajes de error",
87
+ "debug_label": "Estado de depuración",
88
+ "debug_button": "Mostrar estado de depuración",
89
  "model_fast": "Objetos generales (rápido)",
90
  "model_precision": "Objetos generales (precisión alta)",
91
  "model_small": "Objetos pequeños/detalles (lento)",
 
101
  "button": "Détecter les objets",
102
  "info_label": "Information de détection",
103
  "error_label": "Messages d'erreur",
104
+ "debug_label": "État de débogage",
105
+ "debug_button": "Afficher l'état de débogage",
106
  "model_fast": "Objets généraux (rapide)",
107
  "model_precision": "Objets généraux (haute précision)",
108
  "model_small": "Petits objets/détails (lent)",
 
117
 
118
  def get_translated_model_choices(language):
119
  """Get model choices translated to the selected language"""
120
+ global debug_info
121
+ debug_info["step"] = f"Translating model choices for {language}"
122
+
123
  model_mapping = {
124
  "DETR ResNet-50": "model_fast",
125
  "DETR ResNet-101": "model_precision",
 
133
  translation_key = model_mapping[model_key]
134
  translated_name = t(language, translation_key)
135
  else:
136
+ translated_name = model_key
137
  translated_choices.append(translated_name)
138
 
139
+ debug_info["step"] = f"Model choices translated: {translated_choices}"
140
  return translated_choices
141
 
142
 
 
175
  return f"Helsinki-NLP/opus-mt-en-{target}"
176
 
177
 
178
+ # Translation cache
179
  translation_cache = {}
180
 
181
 
 
204
 
205
  def detect_objects(image, language_selector, translated_model_selector, threshold):
206
  """Enhanced object detection with adjustable threshold and better info"""
207
+ global debug_info
208
+
209
  try:
210
+ debug_info["step"] = "Starting object detection"
211
+ debug_info["timestamp"] = str(datetime.datetime.now())
212
+
213
  # Get the actual model key from the translated name
214
  model_selector = get_model_key_from_translation(translated_model_selector, language_selector)
215
+ debug_info["step"] = f"Model key resolved: {model_selector}"
216
 
217
  print(f"Processing image. Language: {language_selector}, Model: {model_selector}, Threshold: {threshold}")
218
 
219
  # Load the selected model
220
+ debug_info["step"] = "Loading model"
221
  model, processor = load_model(model_selector)
222
 
223
  # Process the image
224
+ debug_info["step"] = "Processing image with model"
225
  inputs = processor(images=image, return_tensors="pt")
226
  outputs = model(**inputs)
227
 
228
  # Convert model output to usable detection results with custom threshold
229
+ debug_info["step"] = "Post-processing results"
230
  target_sizes = torch.tensor([image.size[::-1]])
231
  results = processor.post_process_object_detection(
232
  outputs, threshold=threshold, target_sizes=target_sizes
233
  )[0]
234
 
235
  # Create a copy of the image for drawing
236
+ debug_info["step"] = "Drawing bounding boxes"
237
  image_with_boxes = image.copy()
238
  draw = ImageDraw.Draw(image_with_boxes)
239
 
 
303
  else:
304
  detection_info += "No objects detected. Try lowering the threshold."
305
 
306
+ debug_info["step"] = "Detection completed successfully"
307
+ debug_info["last_error"] = ""
308
+
309
+ return image_with_boxes, detection_info, ""
310
 
311
  except Exception as e:
312
  error_message = f"Error in object detection:\n{str(e)}\n\nStack trace:\n{traceback.format_exc()}"
313
+ debug_info["last_error"] = error_message
314
+ debug_info["step"] = f"ERROR in detection: {str(e)}"
315
  print(error_message)
 
316
  return image if image else None, "Detection failed. See error panel below.", error_message
317
 
318
 
319
+ def update_interface(selected_language):
320
+ """Update interface language with comprehensive error handling"""
321
+ global debug_info
322
+
323
+ debug_info["language"] = selected_language
324
+ debug_info["timestamp"] = str(datetime.datetime.now())
325
+ debug_info["step"] = "Starting language interface update"
326
+
327
+ try:
328
+ debug_info["step"] = "Getting translated model choices"
329
+ translated_choices = get_translated_model_choices(selected_language)
330
+
331
+ debug_info["step"] = "Getting default model translation"
332
+ default_model = t(selected_language, "model_fast")
333
+
334
+ debug_info["step"] = "Creating Gradio updates"
335
+
336
+ updates = [
337
+ gr.update(value=t(selected_language, "title")),
338
+ gr.update(label=t(selected_language, "dropdown_label")),
339
+ gr.update(
340
+ choices=translated_choices,
341
+ value=default_model,
342
+ label=t(selected_language, "dropdown_detection_model_label")
343
+ ),
344
+ gr.update(label=t(selected_language, "threshold_label")),
345
+ gr.update(label=t(selected_language, "input_label")),
346
+ gr.update(value=t(selected_language, "button")),
347
+ gr.update(label=t(selected_language, "output_label")),
348
+ gr.update(label=t(selected_language, "info_label")),
349
+ gr.update(label=t(selected_language, "error_label"), value="", visible=False),
350
+ gr.update(label=t(selected_language, "debug_label")),
351
+ gr.update(value=t(selected_language, "debug_button"))
352
+ ]
353
+
354
+ debug_info["step"] = "Interface update completed successfully"
355
+ debug_info["last_error"] = ""
356
+
357
+ return updates
358
+
359
+ except Exception as e:
360
+ error_msg = f"ERROR in interface update at step '{debug_info['step']}':\n{str(e)}\n\nTraceback:\n{traceback.format_exc()}"
361
+ debug_info["last_error"] = error_msg
362
+ debug_info["step"] = f"FAILED: {str(e)}"
363
+
364
+ # Return safe updates that don't change anything
365
+ safe_updates = [gr.update() for _ in range(11)]
366
+ return safe_updates
367
+
368
+
369
+ def get_debug_status():
370
+ """Get current debug status for display"""
371
+ global debug_info
372
+
373
+ status = f"""🔍 DEBUG STATUS:
374
+ Current Language: {debug_info.get('language', 'N/A')}
375
+ Last Timestamp: {debug_info.get('timestamp', 'N/A')}
376
+ Current Step: {debug_info.get('step', 'N/A')}
377
+ Last Error: {debug_info.get('last_error', 'None')}
378
+
379
+ Available Models: {list(available_models.keys())}
380
+ Current Model: {current_model_name or 'None loaded'}
381
+ Translation Cache Size: {len(translation_cache)}
382
+ """
383
+ return status
384
+
385
+
386
+ def safe_detect_objects(image, language_selector, translated_model_selector, threshold):
387
+ """Safe wrapper for object detection with error handling"""
388
+ global debug_info
389
+
390
+ if image is None:
391
+ debug_info["step"] = "No image provided"
392
+ return None, "Please upload an image first.", ""
393
+
394
+ try:
395
+ result_image, info, error = detect_objects(image, language_selector, translated_model_selector, threshold)
396
+
397
+ # Update error panel visibility based on whether there's an error
398
+ error_visible = bool(error.strip())
399
+
400
+ return (
401
+ result_image,
402
+ info,
403
+ gr.update(value=error, visible=error_visible)
404
+ )
405
+
406
+ except Exception as e:
407
+ error_message = f"Unexpected error in detection:\n{str(e)}\n\nStack trace:\n{traceback.format_exc()}"
408
+ debug_info["last_error"] = error_message
409
+ debug_info["step"] = f"UNEXPECTED ERROR: {str(e)}"
410
+ print(error_message)
411
+ return (
412
+ image,
413
+ "Detection failed due to unexpected error. See error panel below.",
414
+ gr.update(value=error_message, visible=True)
415
+ )
416
+
417
+
418
  def build_app():
419
  with gr.Blocks(theme=gr.themes.Soft()) as app:
420
  with gr.Row():
 
430
  with gr.Column(scale=1):
431
  model_selector = gr.Dropdown(
432
  choices=get_translated_model_choices("English"),
433
+ value=t("English", "model_fast"),
434
  label=t("English", "dropdown_detection_model_label")
435
  )
436
  with gr.Column(scale=1):
437
  threshold_slider = gr.Slider(
438
  minimum=0.1,
439
  maximum=0.95,
440
+ value=0.5,
441
  step=0.05,
442
  label=t("English", "threshold_label")
443
  )
 
464
  elem_classes=["error-panel"]
465
  )
466
 
467
+ # Debug panel - always visible for debugging in HF
468
+ with gr.Row():
469
+ debug_panel = gr.Textbox(
470
+ label=t("English", "debug_label"),
471
+ lines=10,
472
+ max_lines=20,
473
+ value="Application started - ready for debugging",
474
+ visible=True
475
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
476
 
477
+ with gr.Row():
478
+ debug_button = gr.Button(t("English", "debug_button"), size="sm")
 
 
 
 
 
 
479
 
480
  # Connect language change event
481
  language_selector.change(
482
  fn=update_interface,
483
  inputs=language_selector,
484
  outputs=[title, language_selector, model_selector, threshold_slider,
485
+ input_image, button, output_image, detection_info, error_panel, debug_panel, debug_button],
486
  queue=False
487
  )
488
 
 
493
  outputs=[output_image, detection_info, error_panel]
494
  )
495
 
496
+ # Connect debug button click event
497
+ debug_button.click(
498
+ fn=get_debug_status,
499
+ outputs=debug_panel
500
+ )
501
+
502
  return app
503
 
504
 
505
+ # Initialize with default model and debug info
506
+ debug_info["step"] = "Initializing default model"
507
+ debug_info["timestamp"] = str(datetime.datetime.now())
508
  load_model("DETR ResNet-50")
509
+ debug_info["step"] = "Application ready"
510
 
511
  # Launch the application
512
  if __name__ == "__main__":