angelo9830 commited on
Commit
9c9ae83
verified
1 Parent(s): f9b6ab5

Upload 2 files

Browse files
Files changed (2) hide show
  1. Dockerfile +30 -0
  2. app.py +65 -0
Dockerfile ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Usa una imagen base de Python
2
+ FROM python:3.11-slim
3
+
4
+ # Crear un nuevo usuario no root para mayor seguridad
5
+ RUN useradd -m -s /bin/bash appuser
6
+
7
+ # Establecer directorio de trabajo
8
+ WORKDIR /home/appuser/app
9
+
10
+ # Instalar dependencias del sistema necesarias para OpenCV
11
+ RUN apt-get update && apt-get install -y libgl1-mesa-glx libglib2.0-0 && apt-get clean
12
+
13
+ # Copiar el archivo de dependencias y instalarlas
14
+ COPY requirements.txt .
15
+ RUN pip install --no-cache-dir -r requirements.txt
16
+
17
+ # Copiar el c贸digo de la aplicaci贸n
18
+ COPY . .
19
+
20
+ # Cambiar permisos al usuario no root
21
+ RUN chown -R appuser:appuser /home/appuser/app
22
+
23
+ # Cambiar al usuario no root
24
+ USER appuser
25
+
26
+ # Exponer el puerto donde correr谩 la aplicaci贸n
27
+ EXPOSE 7860
28
+
29
+ # Comando para iniciar la aplicaci贸n
30
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, UploadFile, HTTPException
2
+ import cv2
3
+ import numpy as np
4
+ from PIL import Image
5
+ import io
6
+ from transformers import ViTFeatureExtractor, ViTForImageClassification
7
+ import torch
8
+
9
+ app = FastAPI()
10
+
11
+ # Cargar el modelo y el extractor de caracter铆sticas
12
+ model = ViTForImageClassification.from_pretrained("nateraw/vit-age-classifier")
13
+ transforms = ViTFeatureExtractor.from_pretrained("nateraw/vit-age-classifier")
14
+
15
+ @app.post("/detect/")
16
+ async def detect_face(file: UploadFile = File(...)):
17
+ # Validar tipo de archivo
18
+ if not file.content_type.startswith("image/"):
19
+ raise HTTPException(status_code=400, detail="El archivo no es una imagen v谩lida.")
20
+
21
+ try:
22
+ # Leer la imagen y convertirla a numpy array
23
+ image_bytes = await file.read()
24
+ image = Image.open(io.BytesIO(image_bytes))
25
+ img_np = np.array(image)
26
+
27
+ # Convertir a formato adecuado (BGR) si tiene transparencia (4 canales)
28
+ if img_np.shape[2] == 4:
29
+ img_np = cv2.cvtColor(img_np, cv2.COLOR_BGRA2BGR)
30
+
31
+ # Detectar rostros con Haar
32
+ face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")
33
+ gray = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
34
+ faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))
35
+
36
+ if len(faces) == 0:
37
+ return {"message": "No se detectaron rostros en la imagen."}
38
+
39
+ results = []
40
+ for (x, y, w, h) in faces:
41
+ # Extraer el rostro y convertirlo a RGB
42
+ face_img = img_np[y:y+h, x:x+w]
43
+ pil_face_img = Image.fromarray(cv2.cvtColor(face_img, cv2.COLOR_BGR2RGB))
44
+
45
+ # Predicci贸n del rango de edad
46
+ inputs = transforms(pil_face_img, return_tensors="pt")
47
+ output = model(**inputs)
48
+ proba = output.logits.softmax(1)
49
+ predicted_class = proba.argmax(1).item()
50
+ predicted_age_range = str(predicted_class) # Mapeo de clases a rangos
51
+
52
+ # A帽adir datos al resultado
53
+ results.append({
54
+ "edad_predicha": predicted_age_range,
55
+ "coordenadas_rostro": {"x": x, "y": y, "w": w, "h": h}
56
+ })
57
+
58
+ return {
59
+ "message": "Rostros detectados y edad predicha.",
60
+ "cantidad_rostros": len(faces),
61
+ "detalles": results
62
+ }
63
+
64
+ except Exception as e:
65
+ raise HTTPException(status_code=500, detail=f"Error procesando la imagen: {str(e)}")