Spaces:
Running
on
Zero
Running
on
Zero
| import gradio as gr | |
| from transformers import pipeline | |
| from PIL import Image, ImageDraw, ImageFont | |
| import torch | |
| import spaces | |
| import numpy as np | |
| import cv2 | |
| # Modèles optimisés pour le temps réel | |
| REALTIME_MODELS = { | |
| "YOLOS Tiny (ultra-rapide)": "hustvl/yolos-tiny", | |
| "DETR ResNet-50": "facebook/detr-resnet-50", | |
| "YOLOS Small": "hustvl/yolos-small", | |
| "Conditional DETR": "microsoft/conditional-detr-resnet-50" | |
| } | |
| # Cache global pour le modèle | |
| current_detector = None | |
| current_model_name = None | |
| def load_detector(model_name): | |
| """Charge le détecteur avec cache""" | |
| global current_detector, current_model_name | |
| if current_model_name != model_name: | |
| print(f"🔄 Chargement du modèle: {model_name}") | |
| model_id = REALTIME_MODELS[model_name] | |
| current_detector = pipeline( | |
| "object-detection", | |
| model=model_id, | |
| device=0 if torch.cuda.is_available() else -1 | |
| ) | |
| current_model_name = model_name | |
| print(f"✅ Modèle chargé: {model_name}") | |
| return current_detector | |
| def process_webcam_frame(frame, model_choice, confidence_threshold): | |
| """ | |
| Traite chaque frame de la webcam en temps réel | |
| Cette fonction est appelée automatiquement pour chaque frame | |
| """ | |
| if frame is None: | |
| return frame | |
| try: | |
| # Charger le détecteur | |
| detector = load_detector(model_choice) | |
| # Convertir numpy array en PIL Image si nécessaire | |
| if isinstance(frame, np.ndarray): | |
| # Gradio webcam donne du RGB | |
| pil_image = Image.fromarray(frame) | |
| else: | |
| pil_image = frame | |
| # Redimensionner pour accélérer le traitement | |
| original_size = pil_image.size | |
| max_size = 640 # Réduire la taille pour plus de vitesse | |
| if max(original_size) > max_size: | |
| ratio = max_size / max(original_size) | |
| new_size = (int(original_size[0] * ratio), int(original_size[1] * ratio)) | |
| resized_image = pil_image.resize(new_size) | |
| else: | |
| resized_image = pil_image | |
| ratio = 1.0 | |
| # Détection sur l'image redimensionnée | |
| detections = detector(resized_image) | |
| # Filtrer par confiance | |
| filtered_detections = [ | |
| det for det in detections | |
| if det['score'] >= confidence_threshold | |
| ] | |
| # Redimensionner les coordonnées vers la taille originale | |
| for det in filtered_detections: | |
| if ratio != 1.0: | |
| det['box']['xmin'] = int(det['box']['xmin'] / ratio) | |
| det['box']['ymin'] = int(det['box']['ymin'] / ratio) | |
| det['box']['xmax'] = int(det['box']['xmax'] / ratio) | |
| det['box']['ymax'] = int(det['box']['ymax'] / ratio) | |
| # Dessiner les détections sur l'image originale | |
| annotated_image = draw_detections_fast(pil_image, filtered_detections) | |
| # Convertir back en numpy pour Gradio | |
| return np.array(annotated_image) | |
| except Exception as e: | |
| print(f"❌ Erreur de traitement: {e}") | |
| return frame | |
| def draw_detections_fast(image, detections): | |
| """Version optimisée pour dessiner les détections""" | |
| if not detections: | |
| return image | |
| draw = ImageDraw.Draw(image) | |
| # Police par défaut pour la vitesse | |
| try: | |
| font = ImageFont.load_default() | |
| except: | |
| font = None | |
| colors = ["#FF6B6B", "#4ECDC4", "#45B7D1", "#96CEB4", "#FECA57"] | |
| for i, detection in enumerate(detections): | |
| box = detection['box'] | |
| label = detection['label'] | |
| score = detection['score'] | |
| # Coordonnées | |
| x1, y1 = box['xmin'], box['ymin'] | |
| x2, y2 = box['xmax'], box['ymax'] | |
| # Couleur | |
| color = colors[i % len(colors)] | |
| # Boîte | |
| draw.rectangle([x1, y1, x2, y2], outline=color, width=2) | |
| # Label avec score | |
| text = f"{label} {score:.2f}" | |
| # Fond du texte (simplifié) | |
| if font: | |
| bbox = draw.textbbox((x1, y1-20), text, font=font) | |
| draw.rectangle(bbox, fill=color) | |
| draw.text((x1, y1-20), text, fill="white", font=font) | |
| else: | |
| draw.text((x1, y1-15), text, fill=color) | |
| return image | |
| # Interface Gradio avec streaming | |
| with gr.Blocks(title="🎥 Détection Live", theme=gr.themes.Soft()) as demo: | |
| gr.Markdown(""" | |
| # 🎥 Détection d'Objets en Temps Réel | |
| **Activez votre webcam** et voyez la détection se faire en direct ! | |
| ⚡ **Optimisé pour la vitesse** avec des modèles légers | |
| """) | |
| with gr.Row(): | |
| with gr.Column(scale=2): | |
| # Composant webcam avec streaming | |
| webcam = gr.Interface( | |
| fn=process_webcam_frame, | |
| inputs=[ | |
| gr.Image(sources=["webcam"], streaming=True, type="numpy"), | |
| gr.Dropdown( | |
| choices=list(REALTIME_MODELS.keys()), | |
| value="YOLOS Tiny (ultra-rapide)", | |
| label="🤖 Modèle (changement en direct)" | |
| ), | |
| gr.Slider( | |
| minimum=0.1, | |
| maximum=1.0, | |
| value=0.5, | |
| step=0.1, | |
| label="🎯 Seuil de confiance" | |
| ) | |
| ], | |
| outputs=gr.Image(type="numpy", streaming=True), | |
| live=True, # ⭐ CRUCIAL: Active le mode live | |
| title=None | |
| ) | |
| with gr.Column(scale=1): | |
| gr.Markdown(""" | |
| ## 📊 Informations Live | |
| ### 🎛️ Contrôles en temps réel: | |
| - **Modèle**: Change instantanément | |
| - **Confiance**: Ajuste le filtrage | |
| - **Streaming**: Traitement frame par frame | |
| ### ⚡ Optimisations: | |
| - Images redimensionnées à 640px | |
| - Modèles légers prioritaires | |
| - Cache intelligent des modèles | |
| - Dessin optimisé | |
| ### 🎯 Modèles recommandés: | |
| - **YOLOS Tiny**: Maximum de vitesse | |
| - **DETR ResNet-50**: Bon équilibre | |
| """) | |
| # Version alternative avec Interface simple | |
| gr.Markdown("---") | |
| gr.Markdown("## 🎥 Version Alternative (Interface Simple)") | |
| alternative_interface = gr.Interface( | |
| fn=process_webcam_frame, | |
| inputs=[ | |
| gr.Image(sources=["webcam"], streaming=True), | |
| gr.Dropdown( | |
| choices=list(REALTIME_MODELS.keys()), | |
| value="YOLOS Tiny (ultra-rapide)" | |
| ), | |
| gr.Slider(0.1, 1.0, 0.5, step=0.1) | |
| ], | |
| outputs=gr.Image(streaming=True), | |
| live=True, # ⭐ Mode live activé | |
| title="Détection Webcam Live", | |
| description="Cliquez sur la webcam pour démarrer le streaming live!" | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() | |