"""Gradio Blocks UI: image / video / webcam tabs plus a JSON API endpoint.""" import gradio as gr from src.configs import settings from src.inference.predictor import Predictor from src.inference.video import annotate_video def _predict_image(predictor: Predictor, image): if image is None: return None, "No image provided", "N/A" result = predictor.classify(image) return result.annotated_frame, result.label, result.confidence_str def _predict_api(predictor: Predictor, image): if image is None: return {"success": False, "error": "No image provided"} try: result = predictor.classify(image) return { "success": True, "class": result.label, "confidence": result.confidence_str, "confidence_value": result.confidence, "threshold_exceeded": result.threshold_exceeded, } except Exception as exc: return {"success": False, "error": str(exc)} def _predict_video(predictor: Predictor, video_path): if video_path is None: return None return annotate_video(video_path, predictor) def build_interface(predictor: Predictor) -> gr.Blocks: with gr.Blocks(title="SerraSafe - Détection de Pestes") as demo: gr.Markdown( f""" # 🌱 SerraSafe Guardian - Système de Détection de Pestes Ce système utilise l'intelligence artificielle pour détecter et classifier les pestes dans votre serre. **Classes détectées:** {", ".join(settings.CLASS_LABELS)} """ ) with gr.Tab("📷 Analyse Image"): with gr.Row(): with gr.Column(): image_input = gr.Image(type="numpy", label="Télécharger une image") image_button = gr.Button("Analyser l'image", variant="primary") with gr.Column(): image_output = gr.Image(label="Résultat") image_label = gr.Textbox(label="Classe détectée") image_confidence = gr.Textbox(label="Confiance") image_button.click( fn=lambda img: _predict_image(predictor, img), inputs=image_input, outputs=[image_output, image_label, image_confidence], ) with gr.Tab("📹 Analyse Vidéo"): with gr.Row(): with gr.Column(): video_input = gr.Video(label="Télécharger une vidéo") video_button = gr.Button("Analyser la vidéo", variant="primary") with gr.Column(): video_output = gr.Video(label="Vidéo annotée") video_button.click( fn=lambda path: _predict_video(predictor, path), inputs=video_input, outputs=video_output, ) with gr.Tab("🎥 Webcam"): gr.Markdown("### Capturez une image avec votre webcam pour l'analyser") with gr.Row(): with gr.Column(): webcam_input = gr.Image(sources=["webcam"], type="numpy", label="Webcam", streaming=False) webcam_button = gr.Button("Analyser", variant="primary") with gr.Column(): webcam_output = gr.Image(label="Résultat") webcam_label = gr.Textbox(label="Classe détectée") webcam_confidence = gr.Textbox(label="Confiance") webcam_button.click( fn=lambda img: _predict_image(predictor, img), inputs=webcam_input, outputs=[webcam_output, webcam_label, webcam_confidence], ) with gr.Tab("🔌 API (JSON)"): gr.Markdown( """ ### API pour clients externes Utilisez cet endpoint pour obtenir des prédictions en JSON. **Endpoint:** `/api/predict` (POST, retourne `class`, `confidence`, `threshold_exceeded`) """ ) with gr.Column(): api_image_input = gr.Image(type="numpy", label="Image") api_button = gr.Button("Tester l'API", variant="primary") api_output = gr.JSON(label="Réponse JSON") api_button.click( fn=lambda img: _predict_api(predictor, img), inputs=api_image_input, outputs=api_output, api_name="predict", ) return demo