Spaces:
Configuration error
Configuration error
fix(backend): add resilient fallbacks for disease, soil, and image preprocessing in serverless environment
254b8d8 | """Image preprocessing pipeline for disease and soil CNN models.""" | |
| import io | |
| import hashlib | |
| from PIL import Image | |
| import numpy as np | |
| try: | |
| import torch | |
| from torchvision import transforms | |
| inference_transform = transforms.Compose([ | |
| transforms.Resize((224, 224)), | |
| transforms.ToTensor(), | |
| ]) | |
| except ImportError: | |
| torch = None | |
| inference_transform = None | |
| def preprocess_image(image_bytes: bytes) -> tuple: | |
| """ | |
| Validate, preprocess and return a (1, 3, 224, 224) float32 tensor/ndarray | |
| plus a deterministic cache key (SHA-256 of raw bytes). | |
| Raises ValueError for invalid / non-image data. | |
| """ | |
| # --- validate --- | |
| try: | |
| img = Image.open(io.BytesIO(image_bytes)) | |
| img.verify() # catches truncated files | |
| img = Image.open(io.BytesIO(image_bytes)) # reopen after verify | |
| except Exception as exc: | |
| raise ValueError(f"Invalid image file: {exc}") from exc | |
| # --- convert to RGB (handles RGBA, palette, grayscale) --- | |
| img = img.convert("RGB") | |
| # --- reject suspiciously small images --- | |
| w, h = img.size | |
| if w < 64 or h < 64: | |
| raise ValueError(f"Image too small ({w}×{h}). Minimum 64×64 px required.") | |
| # --- transform --- | |
| if torch is not None and inference_transform is not None: | |
| tensor = inference_transform(img).unsqueeze(0) # (1, 3, 224, 224) | |
| else: | |
| resized = img.resize((224, 224)) | |
| arr = np.array(resized, dtype=np.float32) / 255.0 | |
| tensor = np.transpose(arr, (2, 0, 1))[np.newaxis, ...] | |
| # --- cache key --- | |
| cache_key = hashlib.sha256(image_bytes).hexdigest() | |
| return tensor, cache_key | |
| def bytes_to_pil(image_bytes: bytes) -> Image.Image: | |
| """Return a PIL Image from raw bytes, converted to RGB.""" | |
| return Image.open(io.BytesIO(image_bytes)).convert("RGB") | |