File size: 2,256 Bytes
52bd289
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
"""
Utilidades de validación y preprocesamiento de imágenes.

Flujo de defensa:
  1. validar_archivo: extensión, tipo MIME, tamaño mínimo
  2. validar_imagen: integridad PIL, dimensiones 32-4000px
  3. preprocess_image: resize 224x224 + normalización ImageNet

Cada función retorna (bool, mensaje) para manejo de errores consistente.
"""

import os
import numpy as np
from PIL import Image, UnidentifiedImageError
from app.config import ALLOWED_EXTENSIONS, ALLOWED_MIMES, IMG_MIN_SIZE, IMG_MAX_SIZE, MIN_FILE_SIZE

def validar_archivo(nombre: str, content_type: str, tamaño: int = -1) -> tuple[bool, str]:
    ext = os.path.splitext(nombre)[1].lower()
    if ext not in ALLOWED_EXTENSIONS:
        return False, f"Formato no soportado: {ext}. Usa: {', '.join(ALLOWED_EXTENSIONS)}"
    if content_type and content_type not in ALLOWED_MIMES:
        return False, f"Tipo MIME no válido: {content_type}"
    if tamaño >= 0 and tamaño < MIN_FILE_SIZE:
        return False, "La imagen es demasiado pequeña o está vacía"
    return True, ""

def validar_imagen(ruta: str) -> tuple[bool, str]:
    try:
        with Image.open(ruta) as img:
            img.verify()
        with Image.open(ruta) as img:
            img.load()
            w, h = img.size
    except (UnidentifiedImageError, Exception):
        return False, "La imagen está corrupta o no es válida"
    if w < IMG_MIN_SIZE or h < IMG_MIN_SIZE:
        return False, f"La imagen es muy pequeña ({w}x{h}). Mínimo: {IMG_MIN_SIZE}px"
    if w > IMG_MAX_SIZE or h > IMG_MAX_SIZE:
        return False, f"La imagen es muy grande ({w}x{h}). Máximo: {IMG_MAX_SIZE}px"
    return True, ""

def preprocess_image(ruta: str) -> np.ndarray:
    """
    Preprocesa imagen para ONNX inference sin torch/torchvision.
    Resize 224x224 + normalizacion ImageNet usando PIL + numpy.
    """
    from PIL import Image
    img = Image.open(ruta).convert('RGB')
    img = img.resize((224, 224), Image.BILINEAR)
    arr = np.array(img, dtype=np.float32) / 255.0
    mean = np.array([0.485, 0.456, 0.406], dtype=np.float32)
    std = np.array([0.229, 0.224, 0.225], dtype=np.float32)
    arr = (arr - mean) / std
    arr = arr.transpose(2, 0, 1)
    arr = np.expand_dims(arr, axis=0)
    return arr