Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import time | |
| import numpy as np | |
| from PIL import Image, ImageOps | |
| from transformers import AutoImageProcessor, AutoModelForImageClassification, pipeline | |
| # Modelo seleccionado (EXISTENTE Y FUNCIONAL) | |
| MODEL_ID = "bazyl/gtsrb-model" | |
| # Cargar preprocesador y modelo | |
| processor = AutoImageProcessor.from_pretrained(MODEL_ID) | |
| model = AutoModelForImageClassification.from_pretrained(MODEL_ID) | |
| classifier = pipeline("image-classification", | |
| model=model, | |
| image_processor=processor, | |
| top_k=3, | |
| device=-1) | |
| # ----------------------------- | |
| # CAPTURA DE IMAGEN DESDE WEBCAM | |
| # ----------------------------- | |
| def capture_frame(frame): | |
| """Convierte la imagen capturada en PIL y corrige espejo.""" | |
| if frame is None: | |
| return None | |
| # Convertir frame a PIL (cuando streaming=False llega como PIL correctamente) | |
| if isinstance(frame, np.ndarray): | |
| frame = Image.fromarray(frame) | |
| # Corregir efecto espejo típico de cámaras frontales | |
| frame = ImageOps.mirror(frame) | |
| return frame | |
| # ----------------------------- | |
| # CLASIFICACIÓN | |
| # ----------------------------- | |
| def predict(img): | |
| if img is None: | |
| return "⚠️ No image has been received.", "-" | |
| start = time.time() | |
| outputs = classifier(img) | |
| end = time.time() | |
| result_text = "\n".join( | |
| [f"{i+1}. {o['label']} ({o['score']*100:.1f}%)" | |
| for i, o in enumerate(outputs)] | |
| ) | |
| return result_text, f"{end - start:.3f} s" | |
| # ----------------------------- | |
| # INTERFAZ GRADIO | |
| # ----------------------------- | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## Traffic Signal Classifier (Camera + Upload images)") | |
| with gr.Row(): | |
| # IMPORTANTE: Para que funcione en portátil, debe ser PIL + NO streaming | |
| webcam = gr.Image( | |
| sources=["webcam"], | |
| streaming=False, # ✔ Captura funciona en PC y móvil | |
| type="pil", # ✔ Los frames se reciben correctamente | |
| label="Camera (preview)" | |
| ) | |
| captured = gr.Image( | |
| type="pil", | |
| label="Captured image", | |
| interactive=False | |
| ) | |
| # Botón de captura | |
| capture_btn = gr.Button("📸 Capture image") | |
| capture_btn.click(fn=capture_frame, inputs=webcam, outputs=captured) | |
| # Subida de imagen alternativa | |
| upload = gr.Image(type="pil", sources=["upload"], label="Upload image from file") | |
| upload.change(lambda img: img, upload, captured) | |
| gr.Markdown("### Classification") | |
| pred_box = gr.Textbox(label="Prediction (top-3)", lines=5) | |
| time_box = gr.Textbox(label="Response time") | |
| classify_btn = gr.Button("Classify") | |
| classify_btn.click(fn=predict, inputs=captured, outputs=[pred_box, time_box]) | |
| demo.launch() | |