Spaces:
Build error
Build error
| # app.py – Hugging Face Spaces avec liste dynamique depuis EC2 + export CSV | |
| import requests | |
| from requests.exceptions import RequestException | |
| import gradio as gr | |
| import base64 | |
| from PIL import Image, ImageDraw | |
| import io | |
| import numpy as np | |
| from collections import deque | |
| import pandas as pd | |
| import tempfile | |
| API_URL = "http://18.212.167.3:8000/predict" | |
| IMAGE_BASE_URL = "http://18.212.167.3:8000/test_images/" | |
| IMAGE_LIST_URL = "http://18.212.167.3:8000/list-test-images" | |
| def generate_dummy_legend(): | |
| class_names = ["Flat", "Construction", "Object", "Nature", "Sky", "Human", "Vehicle", "Ignore"] | |
| colors = [ | |
| (70, 70, 70), # Flat | |
| (128, 64, 128), # Construction | |
| (107, 142, 35), # Object | |
| (0, 0, 0), # Nature | |
| (70, 130, 180), # Sky | |
| (220, 20, 60), # Human | |
| (0, 0, 142), # Vehicle | |
| (102, 102, 156) # Ignore | |
| ] | |
| img = Image.new("RGB", (320, 160), color=(255, 255, 255)) | |
| draw = ImageDraw.Draw(img) | |
| for i, (label, color) in enumerate(zip(class_names, colors)): | |
| y = i * 20 | |
| draw.rectangle([5, y + 5, 25, y + 20], fill=color) | |
| draw.text((30, y + 5), label, fill=(0, 0, 0)) | |
| return img | |
| legend_img = generate_dummy_legend() | |
| history = deque(maxlen=5) | |
| def overlay_mask_on_image(image: Image.Image, mask: Image.Image, alpha: float = 0.5) -> Image.Image: | |
| image = image.convert("RGBA").resize(mask.size) | |
| mask = mask.convert("RGBA") | |
| return Image.blend(image, mask, alpha=alpha) | |
| def segment_image(image: Image.Image, source_name="image_upload.png"): | |
| try: | |
| if image is None: | |
| raise ValueError("Aucune image fournie.") | |
| buffered = io.BytesIO() | |
| image.save(buffered, format="PNG") | |
| buffered.seek(0) | |
| files = {"file": ("input.png", buffered, "image/png")} | |
| response = requests.post(API_URL, files=files, timeout=10) | |
| response.raise_for_status() | |
| data = response.json() | |
| mask_bytes = base64.b64decode(data["mask_base64"]) | |
| mask_image = Image.open(io.BytesIO(mask_bytes)).convert("RGB") | |
| overlay_img = overlay_mask_on_image(image, mask_image) | |
| return image, mask_image, overlay_img, f"{data['inference_time']} sec" | |
| except RequestException as e: | |
| print(f"[ERREUR API EC2] {e}") | |
| return None, None, None, "Erreur : EC2 injoignable ou lente" | |
| except Exception as e: | |
| print(f"[ERREUR GRADIO] {e}") | |
| return None, None, None, f"Erreur : {str(e)}" | |
| def get_remote_image_names(): | |
| try: | |
| response = requests.get(IMAGE_LIST_URL, timeout=5) | |
| response.raise_for_status() | |
| return response.json().get("files", []) | |
| except Exception as e: | |
| print(f"[ERREUR LISTE FICHIERS] {e}") | |
| return ["Erreur lors du chargement des noms"] | |
| def load_image_from_url(filename): | |
| try: | |
| url = IMAGE_BASE_URL + filename | |
| response = requests.get(url, timeout=5) | |
| response.raise_for_status() | |
| return Image.open(io.BytesIO(response.content)).convert("RGB") | |
| except Exception as e: | |
| print(f"[ERREUR CHARGEMENT IMAGE {filename}] {e}") | |
| return None | |
| with gr.Blocks(title="Segmentation d'Images Urbaines") as demo: | |
| gr.Markdown("# 🧠 Segmentation d'Images Urbaines") | |
| gr.Markdown("Upload une image ou sélectionne une image distante depuis EC2") | |
| with gr.Row(): | |
| input_image = gr.Image(type="pil", label="Image d'entrée") | |
| btn = gr.Button("Segmenter") | |
| with gr.Row(): | |
| img_original = gr.Image(label="Image originale") | |
| img_mask = gr.Image(label="Mask prédit") | |
| img_overlay = gr.Image(label="Superposition (image + mask)") | |
| inf_time = gr.Textbox(label="Temps d'inférence") | |
| btn.click(fn=lambda img: segment_image(img), inputs=input_image, | |
| outputs=[img_original, img_mask, img_overlay, inf_time]) | |
| gr.Markdown("## 🌍 Ou sélectionne une image hébergée sur EC2 :") | |
| with gr.Row(): | |
| dropdown = gr.Dropdown(label="Fichier distant (EC2)", choices=get_remote_image_names()) | |
| btn_url = gr.Button("Segmenter cette image distante") | |
| btn_url.click(fn=lambda name: segment_image(load_image_from_url(name), source_name=name), | |
| inputs=dropdown, outputs=[img_original, img_mask, img_overlay, inf_time]) | |
| with gr.Accordion("🎨 Légende des classes", open=False): | |
| gr.Image(value=legend_img, label="Légende (fictive ici)", interactive=False) | |
| if __name__ == "__main__": | |
| demo.launch() | |