Deep_fake_Model_load / utils /image_processor.py
Jay9115's picture
full_commit
eeeea78
Raw History Blame Contribute Delete
3.75 kB
import numpy as np
from PIL import Image
import io
from typing import Tuple, Dict, Union
import asyncio
from concurrent.futures import ThreadPoolExecutor
# Optimized thread pool for CPU-intensive image operations
image_executor = ThreadPoolExecutor(max_workers=2, thread_name_prefix="ImageProcessor")
# Common model input sizes
MODEL_SIZES = {
'xceptionnet': (299, 299),
'mesonet': (256, 256)
}
def _preprocess_image_core(image_data: bytes, target_size: Tuple[int, int]) -> np.ndarray:
"""
Core image preprocessing function (synchronous).
Args:
image_data: Raw image bytes
target_size: Target size as (width, height)
Returns:
Preprocessed numpy array ready for model prediction
"""
# Read and validate image
image = Image.open(io.BytesIO(image_data))
# Convert to RGB if needed
if image.mode != 'RGB':
image = image.convert('RGB')
# Resize and normalize
image = image.resize(target_size, Image.Resampling.LANCZOS)
img_array = np.array(image, dtype=np.float32) / 255.0
# Add batch dimension
return np.expand_dims(img_array, axis=0)
async def preprocess_image(image_data: bytes, target_size: Tuple[int, int]) -> np.ndarray:
"""
Async image preprocessing for FastAPI.
Args:
image_data: Raw image bytes from uploaded file
target_size: Target size as (width, height)
Returns:
Preprocessed numpy array ready for model prediction
"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(image_executor, _preprocess_image_core, image_data, target_size)
async def preprocess_for_models(image_data: bytes) -> Dict[str, np.ndarray]:
"""
Preprocess image for all models simultaneously (optimized).
Args:
image_data: Raw image bytes from uploaded file
Returns:
Dictionary with preprocessed arrays for each model
"""
def _process_all_sizes(data: bytes) -> Dict[str, np.ndarray]:
# Load image once
image = Image.open(io.BytesIO(data))
if image.mode != 'RGB':
image = image.convert('RGB')
results = {}
for model_name, size in MODEL_SIZES.items():
# Resize and normalize
resized = image.resize(size, Image.Resampling.LANCZOS)
img_array = np.array(resized, dtype=np.float32) / 255.0
results[model_name] = np.expand_dims(img_array, axis=0)
return results
loop = asyncio.get_event_loop()
return await loop.run_in_executor(image_executor, _process_all_sizes, image_data)
def validate_image(image_data: bytes) -> bool:
"""
Validate if the provided bytes represent a valid image.
Args:
image_data: Raw image bytes
Returns:
True if valid image, False otherwise
"""
try:
with Image.open(io.BytesIO(image_data)) as img:
img.verify()
return True
except Exception:
return False
# Legacy compatibility function (for any remaining Flask code)
def preprocess_image_sync(file_or_bytes: Union[bytes, object], target_size: Tuple[int, int]) -> np.ndarray:
"""Legacy synchronous preprocessing function for backward compatibility."""
if isinstance(file_or_bytes, bytes):
return _preprocess_image_core(file_or_bytes, target_size)
else:
# Assume it's a file-like object
image = Image.open(file_or_bytes)
if image.mode != 'RGB':
image = image.convert('RGB')
image = image.resize(target_size, Image.Resampling.LANCZOS)
img_array = np.array(image, dtype=np.float32) / 255.0
return np.expand_dims(img_array, axis=0)