from __future__ import annotations import gc import json import pathlib import sys import gradio as gr import PIL.Image import torch from diffusers import StableDiffusionInpaintPipeline class InferencePipeline: def __init__(self): self.pipe = None self.device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") def clear(self) -> None: del self.pipe self.pipe = None torch.cuda.empty_cache() gc.collect() def load_pipe(self, realfill_model: str) -> None: pipe = StableDiffusionInpaintPipeline.from_pretrained( realfill_model, torch_dtype=torch.float16 ).to(self.device) pipe = pipe.to(self.device) self.pipe = pipe def run( self, realfill_model: str, target_image: PIL.Image, target_mask: PIL.Image, seed: int, n_steps: int, guidance_scale: float, ) -> PIL.Image.Image: if not torch.cuda.is_available(): raise gr.Error("CUDA is not available.") self.load_pipe(realfill_model) image = PIL.Image.open(target_image) mask_image = PIL.Image.open(target_mask) generator = torch.Generator(device=self.device).manual_seed(seed) out = self.pipe( "a photo of sks", image=image, mask_image=mask_image, num_inference_steps=n_steps, guidance_scale=guidance_scale, generator=generator, ).images[0] # type: ignore erode_kernel = PIL.ImageFilter.MaxFilter(3) mask_image = mask_image.filter(erode_kernel) result = PIL.Image.composite(result, out, mask_image) return result