LuisTo97's picture
Update app.py
721ac59 verified
Raw
History Blame Contribute Delete
5.07 kB
import streamlit as st
from huggingface_hub import snapshot_download
import tensorflow as tf
import numpy as np
from PIL import Image
import requests
import os
import csv
import datetime
from huggingface_hub import HfApi, Repository
import subprocess
# Configuración de página y tema
st.set_page_config(page_title="GreenVision", page_icon="🌿", layout="centered")
# Banner con logo y título
logo = Image.open("greenvision_logo.png")
st.image(logo, width=70)
st.markdown(
"""
<h1 style="font-weight:800; font-size:2.3rem; margin:0; color:#222; text-align:center;">
GreenVision
</h1>
<div style="text-align:center; color:#444; font-size:1.15rem; margin-top: 0.5em;">
¿No sabes cómo separar tus residuos?<br>
<span style="color:#007aff; font-weight:500;">¡Usa GreenVision y descúbrelo al instante!</span><br>
<span style="font-size:0.95rem; color:#888;">Sube una foto y nuestra IA te dirá el tipo de residuo.</span>
</div>
""",
unsafe_allow_html=True,
)
CACHE_DIR = "/tmp/hf_cache"
os.makedirs(CACHE_DIR, exist_ok=True)
os.environ["HF_HOME"] = CACHE_DIR
@st.cache_resource
def load_model():
model_dir = snapshot_download(
repo_id="LuisTo97/greenvisionmodel",
cache_dir=CACHE_DIR
)
return tf.keras.models.load_model(model_dir, compile=False)
model = load_model()
CLASS_NAMES = ['Hazardous', 'Organic', 'Recyclable', 'Non-Recyclable']
uploaded_file = st.file_uploader("Sube aquí tus residuos", type=["jpg", "jpeg", "png"])
if uploaded_file is not None:
image = Image.open(uploaded_file).convert("RGB")
img = image.resize((224, 224))
arr = np.array(img, dtype=np.float32) / 255.0
arr = np.expand_dims(arr, axis=0)
preds = model.predict(arr)[0]
idx = np.argmax(preds)
prediction = CLASS_NAMES[idx]
# Tarjeta de predicción y sugerencia
suggestions = {
"Hazardous": "Llévalo a un punto limpio o centro de acopio especializado.",
"Organic": "Puedes compostarlo o tirarlo en el contenedor orgánico.",
"Recyclable": "¡No olvides enjuagarlo antes de reciclar!",
"Non-Recyclable": "Deposítalo en el contenedor gris o de basura general."
}
st.markdown(
f"""
<div style='background: #f5f7fa; border-radius: 16px; padding: 1.5em 1em; margin-top: 1.5em; color: #222; font-size: 1.13rem; text-align: center; box-shadow: 0 2px 8px #0001;'>
<span style='font-size:2.2rem; display:inline-block; margin-bottom:0.3em;'>✅</span><br>
<b>¡Listo! Este residuo es:</b><br>
<span style='font-size:1.5rem; color:#007aff; font-weight:600;'>{prediction}</span>
<div style='margin-top:1.1em; color:#444; font-size:1.07rem;'>
<b>Sugerencia:</b> {suggestions.get(prediction, '')}
</div>
</div>
""",
unsafe_allow_html=True,
)
# Imagen cargada
st.image(image, caption="Imagen subida", use_container_width=True)
# Feedback
st.markdown("---")
st.markdown(
"<div style='font-size:1.1rem; font-weight:500; margin-bottom: 0.5em;'>¿La predicción fue correcta? <span style='color:#007aff'>¡Ayúdanos a mejorar!</span></div>",
unsafe_allow_html=True,
)
col1, col2 = st.columns(2)
with col1:
correct_prediction = st.radio("¿Es correcta la predicción?", ["Sí", "No"], horizontal=True)
with col2:
true_label = st.selectbox("Si no es correcta, ¿cuál debería ser?", CLASS_NAMES)
if st.button("Enviar Feedback"):
api = HfApi()
FEED_PATH = "/tmp/feedback_log.csv"
try:
api.download_file(
repo_id="LuisTo97/GreenVision-Docker",
repo_type="space",
path_in_repo="feedback_log.csv",
local_path=FEED_PATH,
token=os.getenv("HUGGINGFACE_HUB_TOKEN")
)
file_exists = True
except Exception:
# no existía aún
file_exists = False
with open(FEED_PATH, "a", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
if not file_exists:
writer.writerow(["predicted", "correct", "timestamp"])
writer.writerow([
prediction,
true_label if correct_prediction == "No" else prediction,
datetime.datetime.utcnow().isoformat()
])
st.success("¡Feedback guardado localmente en /tmp!")
api.upload_file(
path_or_fileobj=FEED_PATH,
path_in_repo="feedback_log.csv",
repo_id="LuisTo97/GreenVision-Docker",
repo_type="space",
token=os.getenv("HUGGINGFACE_HUB_TOKEN"),
commit_message="Add new feedback entry"
)
st.info("¡Feedback subido y acumulado en el repositorio!")
else:
# Mensaje de espera
st.markdown(
"<div style='color:#888; text-align:center; margin-top:3em; font-size:1.15rem;'>"
"Arrastra o selecciona una imagen para descubrir cómo clasificar tu residuo ♻️"
"</div>",
unsafe_allow_html=True,
)