Spaces:
Sleeping
Sleeping
| import numpy as np | |
| from PIL import Image, ImageOps | |
| import io | |
| TARGET_SIZE = (224, 224) | |
| def preprocess_image(filepath: str) -> np.ndarray: | |
| """ | |
| Full preprocessing pipeline: | |
| 1. Load image | |
| 2. Convert to RGB | |
| 3. EXIF-aware rotation | |
| 4. Resize to 224x224 | |
| 5. Normalize to [0, 1] | |
| Returns: np.ndarray of shape (224, 224, 3) | |
| """ | |
| img = Image.open(filepath) | |
| # Fix EXIF orientation | |
| try: | |
| img = ImageOps.exif_transpose(img) | |
| except Exception: | |
| pass | |
| # Ensure RGB (handle RGBA, grayscale, palette) | |
| if img.mode != "RGB": | |
| img = img.convert("RGB") | |
| # Resize using high-quality Lanczos resampling | |
| img = img.resize(TARGET_SIZE, Image.LANCZOS) | |
| # Convert to numpy float32 array | |
| arr = np.array(img, dtype=np.float32) | |
| # Normalize to [0, 1] | |
| arr = arr / 255.0 | |
| return arr | |
| def preprocess_from_bytes(image_bytes: bytes) -> np.ndarray: | |
| """Preprocess image from raw bytes (for streaming use).""" | |
| img = Image.open(io.BytesIO(image_bytes)) | |
| try: | |
| img = ImageOps.exif_transpose(img) | |
| except Exception: | |
| pass | |
| if img.mode != "RGB": | |
| img = img.convert("RGB") | |
| img = img.resize(TARGET_SIZE, Image.LANCZOS) | |
| arr = np.array(img, dtype=np.float32) / 255.0 | |
| return arr | |
| def validate_image(filepath: str) -> tuple[bool, str]: | |
| """ | |
| Validate that file is a readable image. | |
| Returns (is_valid, error_message). | |
| """ | |
| try: | |
| img = Image.open(filepath) | |
| img.verify() | |
| return True, "" | |
| except Exception as e: | |
| return False, f"Invalid image file: {str(e)}" | |