import base64 import io from typing import Dict, Any, Optional from PIL import Image import numpy as np import requests class DynamicImageOutpainter: """ A sophisticated image processing class for iterative outpainting and padding. ## Key Features: - Dynamic image cropping and centering - Iterative outpainting with configurable steps - Flexible padding mechanism - AI-driven edge generation ## Usage Strategy: 1. Initialize with base image and generation parameters 2. Apply iterative padding and outpainting 3. Support multiple AI inference backends """ def __init__( self, endpoint_url: str, api_token: str, padding_size: int = 256, max_iterations: int = 3 ): """ Initialize the outpainting processor. Args: endpoint_url (str): AI inference endpoint URL api_token (str): Authentication token for API padding_size (int): Size of padding around cropped image max_iterations (int): Maximum number of outpainting iterations """ self.endpoint_url = endpoint_url self.api_token = api_token self.padding_size = padding_size self.max_iterations = max_iterations self.headers = { "Authorization": f"Bearer {self.api_token}", "Content-Type": "application/json", "Accept": "image/png" } def encode_image(self, image: Image.Image) -> str: """ Base64 encode a PIL Image for API transmission. Args: image (Image.Image): Source image to encode Returns: str: Base64 encoded image string """ buffered = io.BytesIO() image.save(buffered, format="PNG") return base64.b64encode(buffered.getvalue()).decode("utf-8") def crop_to_center(self, image: Image.Image) -> Image.Image: """ Crop image to its center, maintaining square aspect ratio. Args: image (Image.Image): Source image Returns: Image.Image: Center-cropped image """ width, height = image.size size = min(width, height) left = (width - size) // 2 top = (height - size) // 2 right = left + size bottom = top + size return image.crop((left, top, right, bottom)) def create_padding_mask(self, image: Image.Image) -> Image.Image: """ Generate a mask for padding regions. Args: image (Image.Image): Source image Returns: Image.Image: Mask indicating padding regions """ mask = Image.new('L', image.size, 0) mask_array = np.array(mask) # Set padding regions to white (255) mask_array[:self.padding_size, :] = 255 # Top mask_array[-self.padding_size:, :] = 255 # Bottom mask_array[:, :self.padding_size] = 255 # Left mask_array[:, -self.padding_size:] = 255 # Right return Image.fromarray(mask_array) def pad_image(self, image: Image.Image) -> Image.Image: """ Add padding around the image. Args: image (Image.Image): Source image Returns: Image.Image: Padded image """ padded_size = ( image.width + 2 * self.padding_size, image.height + 2 * self.padding_size ) padded_image = Image.new('RGBA', padded_size, (0, 0, 0, 0)) padded_image.paste(image, (self.padding_size, self.padding_size)) return padded_image def predict_outpainting( self, image: Image.Image, mask_image: Image.Image, prompt: str ) -> Image.Image: """ Call AI inference endpoint for outpainting. Args: image (Image.Image): Base image mask_image (Image.Image): Padding mask prompt (str): Outpainting generation prompt Returns: Image.Image: Outpainted result """ payload = { "inputs": prompt, "image": self.encode_image(image), "mask_image": self.encode_image(mask_image) } try: response = requests.post( self.endpoint_url, headers=self.headers, json=payload ) response.raise_for_status() return Image.open(io.BytesIO(response.content)) except requests.RequestException as e: print(f"Outpainting request failed: {e}") return image def process_iterative_outpainting( self, initial_image: Image.Image, prompt: str ) -> Image.Image: """ Execute iterative outpainting process. Args: initial_image (Image.Image): Starting image prompt (str): Generation prompt Returns: Image.Image: Final outpainted image """ current_image = self.crop_to_center(initial_image) for iteration in range(self.max_iterations): padded_image = self.pad_image(current_image) mask = self.create_padding_mask(padded_image) current_image = self.predict_outpainting( padded_image, mask, prompt ) return current_image def run( self, image_path: str, prompt: str ) -> Dict[str, Any]: """ Main processing method for dynamic outpainting. Args: image_path (str): Path to input image prompt (str): Outpainting generation prompt Returns: Dict containing processing results """ try: initial_image = Image.open(image_path) result_image = self.process_iterative_outpainting( initial_image, prompt ) # Optional: Save result result_path = f"outpainted_result_{id(self)}.png" result_image.save(result_path) return { "status": "success", "result_path": result_path, "iterations": self.max_iterations } except Exception as e: return { "status": "error", "message": str(e) } # Usage Example def main(): outpainter = DynamicImageOutpainter( endpoint_url="https://your-ai-endpoint.com", api_token="your_huggingface_token", padding_size=256, max_iterations=3 ) result = outpainter.run( image_path="input_image.png", prompt="Expand the scene with natural, seamless background" ) print(result) if __name__ == "__main__": main()