Spaces:
Sleeping
Sleeping
| """Image preprocessing utilities.""" | |
| import numpy as np | |
| from PIL import Image | |
| import hashlib | |
| from typing import Tuple, Optional | |
| def preprocess_image(image_input, max_size: int = 1024) -> Image.Image: | |
| """ | |
| Preprocess any image input into a standardized PIL RGB image. | |
| Args: | |
| image_input: PIL Image, numpy array, or file path | |
| max_size: maximum dimension for resizing | |
| Returns: | |
| PIL Image in RGB mode, resized to max_size if needed | |
| """ | |
| if isinstance(image_input, str): | |
| img = Image.open(image_input).convert("RGB") | |
| elif isinstance(image_input, np.ndarray): | |
| if image_input.ndim == 2: | |
| img = Image.fromarray(image_input).convert("RGB") | |
| elif image_input.ndim == 3: | |
| img = Image.fromarray(image_input).convert("RGB") | |
| else: | |
| raise ValueError(f"Unexpected array shape: {image_input.shape}") | |
| elif isinstance(image_input, Image.Image): | |
| img = image_input.convert("RGB") | |
| else: | |
| raise TypeError(f"Unsupported image type: {type(image_input)}") | |
| # Resize if too large | |
| w, h = img.size | |
| if max(w, h) > max_size: | |
| scale = max_size / max(w, h) | |
| new_w, new_h = int(w * scale), int(h * scale) | |
| img = img.resize((new_w, new_h), Image.LANCZOS) | |
| return img | |
| def compute_image_hash(img: Image.Image) -> str: | |
| """Compute SHA256 hash of image pixels for caching.""" | |
| return hashlib.sha256(np.array(img).tobytes()).hexdigest() | |
| def get_image_size(img: Image.Image) -> Tuple[int, int]: | |
| """Return (width, height) of image.""" | |
| return img.size | |
| def validate_image(img: Image.Image, min_size: int = 50) -> Optional[str]: | |
| """ | |
| Validate image meets minimum requirements. | |
| Returns error message if invalid, None if valid. | |
| """ | |
| w, h = img.size | |
| if w < min_size or h < min_size: | |
| return f"Image too small: {w}x{h}. Minimum {min_size}x{min_size} required." | |
| return None | |