Spaces:
Sleeping
Sleeping
import io | |
import pickle | |
import numpy as np | |
import tensorflow as tf | |
from fastapi import FastAPI, File, UploadFile, HTTPException | |
from fastapi.middleware.cors import CORSMiddleware | |
from PIL import Image | |
from minisom import MiniSom | |
app = FastAPI(title="API de Clasificación de Señas con Modelo Híbrido (CNN+SOM)") | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=["*"], | |
allow_credentials=True, | |
allow_methods=["*"], | |
allow_headers=["*"], | |
) | |
try: | |
feature_extractor = tf.keras.models.load_model('feature_extractor.keras') | |
print("✅ Extractor de características (feature_extractor.keras) cargado.") | |
with open('som_model.pkl', 'rb') as f: | |
som_data = pickle.load(f) | |
som = som_data['som'] | |
label_map = som_data['label_map'] | |
class_names = som_data['class_names'] | |
print("✅ Modelo SOM (som_model.pkl) y etiquetas cargados.") | |
except Exception as e: | |
print(f"❌ Error fatal al cargar los modelos: {e}") | |
feature_extractor = None | |
som = None | |
label_map = None | |
class_names = None | |
IMG_SIZE = 224 | |
def process_image(image_bytes: bytes): | |
try: | |
image = Image.open(io.BytesIO(image_bytes)).convert("RGB") | |
image = image.resize((IMG_SIZE, IMG_SIZE)) | |
image_array = np.array(image) / 255.0 | |
return np.expand_dims(image_array, axis=0) | |
except Exception as e: | |
raise HTTPException(status_code=400, detail=f"Fallo en el procesamiento de imagen: {e}") | |
async def translate_sign(file: UploadFile = File(...)): | |
if not all([feature_extractor, som, label_map, class_names]): | |
raise HTTPException(status_code=500, detail="Los modelos no están cargados. El servidor no puede procesar la petición.") | |
image_bytes = await file.read() | |
processed_image = process_image(image_bytes) | |
feature_vector = feature_extractor.predict(processed_image) | |
winner_neuron = som.winner(feature_vector[0]) # [0] para quitar la dimensión de batch | |
predicted_class_index = label_map.get(winner_neuron) | |
if predicted_class_index is None: | |
return {"prediction": "Desconocido", "confidence": 0.0} | |
predicted_label = class_names[predicted_class_index] | |
return {"prediction": predicted_label, "confidence": 0.9} | |
def read_root(): | |
return {"message": "API para modelo híbrido CNN+SOM funcionando."} |