Spaces:
Sleeping
Sleeping
Alex Vega
commited on
Commit
路
4dbd30d
1
Parent(s):
f930c12
up
Browse files- Dockerfile +13 -0
- main.py +67 -0
Dockerfile
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.9-slim
|
2 |
+
|
3 |
+
WORKDIR /app
|
4 |
+
|
5 |
+
COPY requirements.txt .
|
6 |
+
|
7 |
+
RUN pip install --no-cache-dir --upgrade pip -r requirements.txt
|
8 |
+
|
9 |
+
COPY . .
|
10 |
+
|
11 |
+
EXPOSE 8000
|
12 |
+
|
13 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
main.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# main.py
|
2 |
+
|
3 |
+
import io
|
4 |
+
import numpy as np
|
5 |
+
import tensorflow as tf
|
6 |
+
from fastapi import FastAPI, File, UploadFile
|
7 |
+
from fastapi.responses import JSONResponse
|
8 |
+
from PIL import Image
|
9 |
+
from pydantic import BaseModel
|
10 |
+
|
11 |
+
class TranslationResponse(BaseModel):
|
12 |
+
prediction: str
|
13 |
+
confidence: float
|
14 |
+
|
15 |
+
try:
|
16 |
+
model = tf.keras.models.load_model('best_model.keras')
|
17 |
+
except Exception as e:
|
18 |
+
raise IOError(f"Error al cargar el modelo 'best_model.keras'. Aseg煤rate de que el archivo est谩 en el directorio correcto. Error: {e}")
|
19 |
+
|
20 |
+
app = FastAPI(
|
21 |
+
title="API de Traducci贸n de Lenguaje de Se帽as Americano",
|
22 |
+
description="Sube una imagen del alfabeto de se帽as (ASL) para obtener una predicci贸n del modelo.",
|
23 |
+
version="1.0.0"
|
24 |
+
)
|
25 |
+
|
26 |
+
CLASS_NAMES = [
|
27 |
+
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
28 |
+
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
29 |
+
'del', 'nothing', 'space'
|
30 |
+
]
|
31 |
+
|
32 |
+
def preprocess_image(image: Image.Image) -> np.ndarray:
|
33 |
+
image = image.resize((96, 96))
|
34 |
+
image_array = np.array(image)
|
35 |
+
|
36 |
+
# Si la imagen es RGBA o en escala de grises, la convierte a RGB
|
37 |
+
if image_array.shape[2] == 4:
|
38 |
+
image_array = image_array[..., :3]
|
39 |
+
|
40 |
+
# Normaliza y expande dimensiones para que coincida con la entrada del modelo (1, 96, 96, 3)
|
41 |
+
normalized_array = image_array.astype('float32') / 255.0
|
42 |
+
return np.expand_dims(normalized_array, axis=0)
|
43 |
+
|
44 |
+
@app.post("/predict/", response_model=TranslationResponse)
|
45 |
+
async def predict(file: UploadFile = File(...)):
|
46 |
+
contents = await file.read()
|
47 |
+
|
48 |
+
try:
|
49 |
+
image = Image.open(io.BytesIO(contents)).convert('RGB')
|
50 |
+
except Exception as e:
|
51 |
+
return JSONResponse(status_code=400, content={"message": f"Error al leer la imagen: {e}"})
|
52 |
+
|
53 |
+
processed_image = preprocess_image(image)
|
54 |
+
|
55 |
+
predictions = model.predict(processed_image)
|
56 |
+
|
57 |
+
predicted_index = np.argmax(predictions, axis=1)[0]
|
58 |
+
|
59 |
+
confidence = float(predictions[0][predicted_index])
|
60 |
+
|
61 |
+
prediction_label = CLASS_NAMES[predicted_index]
|
62 |
+
|
63 |
+
return TranslationResponse(prediction=prediction_label, confidence=confidence)
|
64 |
+
|
65 |
+
@app.get("/")
|
66 |
+
def read_root():
|
67 |
+
return {"message": "ok"}
|