Spaces:
Sleeping
Sleeping
| 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 | |
| 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, | |
| ) |