Spaces:
Sleeping
Sleeping
| # app/utils/image_utils.py | |
| # Image preprocessing and manipulation utilities | |
| from io import BytesIO | |
| from PIL import Image | |
| import numpy as np | |
| def load_image_from_bytes(data: bytes) -> Image.Image: | |
| """Load a PIL Image from raw bytes.""" | |
| return Image.open(BytesIO(data)).convert("RGB") | |
| def resize_image(image: Image.Image, size: tuple[int, int] = (224, 224)) -> Image.Image: | |
| """Resize image to target dimensions, maintaining aspect ratio with center crop.""" | |
| image = image.resize(size, Image.Resampling.LANCZOS) | |
| return image | |
| def image_to_numpy(image: Image.Image) -> np.ndarray: | |
| """Convert PIL Image to normalized numpy array (C, H, W) float32.""" | |
| arr = np.array(image, dtype=np.float32) / 255.0 | |
| # HWC β CHW | |
| arr = np.transpose(arr, (2, 0, 1)) | |
| return arr | |
| def normalize_image( | |
| arr: np.ndarray, | |
| mean: tuple[float, ...] = (0.485, 0.456, 0.406), | |
| std: tuple[float, ...] = (0.229, 0.224, 0.225), | |
| ) -> np.ndarray: | |
| """Apply ImageNet normalization to a CHW numpy array.""" | |
| mean_arr = np.array(mean, dtype=np.float32).reshape(3, 1, 1) | |
| std_arr = np.array(std, dtype=np.float32).reshape(3, 1, 1) | |
| return (arr - mean_arr) / std_arr | |
| def preprocess_image_for_model( | |
| image: Image.Image, size: tuple[int, int] = (224, 224) | |
| ) -> np.ndarray: | |
| """Full preprocessing pipeline: resize β numpy β normalize β add batch dim.""" | |
| image = resize_image(image, size) | |
| arr = image_to_numpy(image) | |
| arr = normalize_image(arr) | |
| return np.expand_dims(arr, axis=0) # (1, C, H, W) | |
| def image_to_base64(image: Image.Image, fmt: str = "JPEG", quality: int = 85) -> str: | |
| """Encode PIL Image as base64 string.""" | |
| import base64 | |
| buffer = BytesIO() | |
| image.save(buffer, format=fmt, quality=quality) | |
| return base64.b64encode(buffer.getvalue()).decode("utf-8") | |