nounouille
� Revert : retour à version stable sans export CSV
5ae7114
# 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()