Spaces:
Sleeping
Sleeping
File size: 1,620 Bytes
953bea8 | 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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | 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)}"
|