Spaces:
Build error
Build error
nounouille commited on
Commit ·
0171016
1
Parent(s): 004c451
� Ajout de pandas dans requirements + export CSV dans app.py
Browse files- app.py +27 -5
- requirements.txt +2 -1
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
# app.py – Hugging Face Spaces avec liste dynamique depuis EC2
|
| 2 |
|
| 3 |
import requests
|
| 4 |
from requests.exceptions import RequestException
|
|
@@ -8,6 +8,7 @@ from PIL import Image
|
|
| 8 |
import io
|
| 9 |
import numpy as np
|
| 10 |
from collections import deque
|
|
|
|
| 11 |
|
| 12 |
API_URL = "http://18.212.167.3:8000/predict"
|
| 13 |
IMAGE_BASE_URL = "http://18.212.167.3:8000/test_images/"
|
|
@@ -15,13 +16,14 @@ IMAGE_LIST_URL = "http://18.212.167.3:8000/list-test-images"
|
|
| 15 |
|
| 16 |
legend_img = Image.new("RGB", (300, 50), color=(128, 128, 128))
|
| 17 |
history = deque(maxlen=5)
|
|
|
|
| 18 |
|
| 19 |
def overlay_mask_on_image(image: Image.Image, mask: Image.Image, alpha: float = 0.5) -> Image.Image:
|
| 20 |
image = image.convert("RGBA").resize(mask.size)
|
| 21 |
mask = mask.convert("RGBA")
|
| 22 |
return Image.blend(image, mask, alpha=alpha)
|
| 23 |
|
| 24 |
-
def segment_image(image: Image.Image):
|
| 25 |
try:
|
| 26 |
if image is None:
|
| 27 |
raise ValueError("Aucune image fournie.")
|
|
@@ -37,6 +39,13 @@ def segment_image(image: Image.Image):
|
|
| 37 |
mask_bytes = base64.b64decode(data["mask_base64"])
|
| 38 |
mask_image = Image.open(io.BytesIO(mask_bytes)).convert("RGB")
|
| 39 |
overlay_img = overlay_mask_on_image(image, mask_image)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
return image, mask_image, overlay_img, f"{data['inference_time']} sec"
|
| 41 |
|
| 42 |
except RequestException as e:
|
|
@@ -66,6 +75,13 @@ def load_image_from_url(filename):
|
|
| 66 |
print(f"[ERREUR CHARGEMENT IMAGE {filename}] {e}")
|
| 67 |
return None
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
with gr.Blocks(title="Segmentation d'Images Urbaines") as demo:
|
| 70 |
gr.Markdown("# 🧠 Segmentation d'Images Urbaines")
|
| 71 |
gr.Markdown("Upload une image ou sélectionne une image distante depuis EC2")
|
|
@@ -78,14 +94,20 @@ with gr.Blocks(title="Segmentation d'Images Urbaines") as demo:
|
|
| 78 |
img_mask = gr.Image(label="Mask prédit")
|
| 79 |
img_overlay = gr.Image(label="Superposition (image + mask)")
|
| 80 |
inf_time = gr.Textbox(label="Temps d'inférence")
|
| 81 |
-
btn.click(fn=segment_image, inputs=input_image,
|
|
|
|
| 82 |
|
| 83 |
gr.Markdown("## 🌍 Ou sélectionne une image hébergée sur EC2 :")
|
| 84 |
with gr.Row():
|
| 85 |
dropdown = gr.Dropdown(label="Fichier distant (EC2)", choices=get_remote_image_names())
|
| 86 |
btn_url = gr.Button("Segmenter cette image distante")
|
| 87 |
-
btn_url.click(fn=lambda name: segment_image(load_image_from_url(name)
|
| 88 |
-
outputs=[img_original, img_mask, img_overlay, inf_time])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
with gr.Accordion("🎨 Légende des classes", open=False):
|
| 91 |
gr.Image(value=legend_img, label="Légende (fictive ici)", interactive=False)
|
|
|
|
| 1 |
+
# app.py – Hugging Face Spaces avec liste dynamique depuis EC2 + export CSV
|
| 2 |
|
| 3 |
import requests
|
| 4 |
from requests.exceptions import RequestException
|
|
|
|
| 8 |
import io
|
| 9 |
import numpy as np
|
| 10 |
from collections import deque
|
| 11 |
+
import pandas as pd
|
| 12 |
|
| 13 |
API_URL = "http://18.212.167.3:8000/predict"
|
| 14 |
IMAGE_BASE_URL = "http://18.212.167.3:8000/test_images/"
|
|
|
|
| 16 |
|
| 17 |
legend_img = Image.new("RGB", (300, 50), color=(128, 128, 128))
|
| 18 |
history = deque(maxlen=5)
|
| 19 |
+
history_csv = []
|
| 20 |
|
| 21 |
def overlay_mask_on_image(image: Image.Image, mask: Image.Image, alpha: float = 0.5) -> Image.Image:
|
| 22 |
image = image.convert("RGBA").resize(mask.size)
|
| 23 |
mask = mask.convert("RGBA")
|
| 24 |
return Image.blend(image, mask, alpha=alpha)
|
| 25 |
|
| 26 |
+
def segment_image(image: Image.Image, source_name="image_upload.png"):
|
| 27 |
try:
|
| 28 |
if image is None:
|
| 29 |
raise ValueError("Aucune image fournie.")
|
|
|
|
| 39 |
mask_bytes = base64.b64decode(data["mask_base64"])
|
| 40 |
mask_image = Image.open(io.BytesIO(mask_bytes)).convert("RGB")
|
| 41 |
overlay_img = overlay_mask_on_image(image, mask_image)
|
| 42 |
+
|
| 43 |
+
# Ajout dans l'historique CSV
|
| 44 |
+
history_csv.append({
|
| 45 |
+
"filename": source_name,
|
| 46 |
+
"inference_time": round(float(data["inference_time"]), 3)
|
| 47 |
+
})
|
| 48 |
+
|
| 49 |
return image, mask_image, overlay_img, f"{data['inference_time']} sec"
|
| 50 |
|
| 51 |
except RequestException as e:
|
|
|
|
| 75 |
print(f"[ERREUR CHARGEMENT IMAGE {filename}] {e}")
|
| 76 |
return None
|
| 77 |
|
| 78 |
+
def export_csv():
|
| 79 |
+
if not history_csv:
|
| 80 |
+
return gr.File.update(value=None, visible=False)
|
| 81 |
+
df = pd.DataFrame(history_csv)
|
| 82 |
+
csv_bytes = df.to_csv(index=False).encode()
|
| 83 |
+
return gr.File.update(value=io.BytesIO(csv_bytes), visible=True, label="📥 Résultats CSV")
|
| 84 |
+
|
| 85 |
with gr.Blocks(title="Segmentation d'Images Urbaines") as demo:
|
| 86 |
gr.Markdown("# 🧠 Segmentation d'Images Urbaines")
|
| 87 |
gr.Markdown("Upload une image ou sélectionne une image distante depuis EC2")
|
|
|
|
| 94 |
img_mask = gr.Image(label="Mask prédit")
|
| 95 |
img_overlay = gr.Image(label="Superposition (image + mask)")
|
| 96 |
inf_time = gr.Textbox(label="Temps d'inférence")
|
| 97 |
+
btn.click(fn=lambda img: segment_image(img), inputs=input_image,
|
| 98 |
+
outputs=[img_original, img_mask, img_overlay, inf_time])
|
| 99 |
|
| 100 |
gr.Markdown("## 🌍 Ou sélectionne une image hébergée sur EC2 :")
|
| 101 |
with gr.Row():
|
| 102 |
dropdown = gr.Dropdown(label="Fichier distant (EC2)", choices=get_remote_image_names())
|
| 103 |
btn_url = gr.Button("Segmenter cette image distante")
|
| 104 |
+
btn_url.click(fn=lambda name: segment_image(load_image_from_url(name), source_name=name),
|
| 105 |
+
inputs=dropdown, outputs=[img_original, img_mask, img_overlay, inf_time])
|
| 106 |
+
|
| 107 |
+
with gr.Row():
|
| 108 |
+
btn_export = gr.Button("📤 Exporter CSV des inférences")
|
| 109 |
+
file_output = gr.File(visible=False)
|
| 110 |
+
btn_export.click(fn=export_csv, inputs=[], outputs=file_output)
|
| 111 |
|
| 112 |
with gr.Accordion("🎨 Légende des classes", open=False):
|
| 113 |
gr.Image(value=legend_img, label="Légende (fictive ici)", interactive=False)
|
requirements.txt
CHANGED
|
@@ -4,4 +4,5 @@ matplotlib-inline==0.1.7
|
|
| 4 |
numpy==1.26.4
|
| 5 |
pandas==2.2.1
|
| 6 |
pillow==10.3.0
|
| 7 |
-
requests==2.32.3
|
|
|
|
|
|
| 4 |
numpy==1.26.4
|
| 5 |
pandas==2.2.1
|
| 6 |
pillow==10.3.0
|
| 7 |
+
requests==2.32.3
|
| 8 |
+
pandas==2.2.1
|