Spaces:
Running
Running
import os | |
import sys | |
import glob | |
import argparse | |
import torch | |
import numpy as np | |
import PIL.Image as Image | |
from pathlib import Path | |
from diffusers import StableDiffusionInpaintPipeline | |
from utils.mask_processing import crop_for_filling_pre, crop_for_filling_post | |
from utils.crop_for_replacing import recover_size, resize_and_pad | |
from utils import load_img_to_array, save_array_to_img | |
def fill_img_with_sd( | |
img: np.ndarray, mask: np.ndarray, text_prompt: str, device="cuda" | |
): | |
pipe = StableDiffusionInpaintPipeline.from_pretrained( | |
"stabilityai/stable-diffusion-2-inpainting", | |
torch_dtype=torch.float32, | |
).to(device) | |
img_crop, mask_crop = crop_for_filling_pre(img, mask) | |
img_crop_filled = pipe( | |
prompt=text_prompt, | |
image=Image.fromarray(img_crop), | |
mask_image=Image.fromarray(mask_crop), | |
).images[0] | |
img_filled = crop_for_filling_post(img, mask, np.array(img_crop_filled)) | |
return img_filled | |
def replace_img_with_sd( | |
img: np.ndarray, mask: np.ndarray, text_prompt: str, step: int = 50, device="cuda" | |
): | |
pipe = StableDiffusionInpaintPipeline.from_pretrained( | |
"stabilityai/stable-diffusion-2-inpainting", | |
torch_dtype=torch.float32, | |
).to(device) | |
img_padded, mask_padded, padding_factors = resize_and_pad(img, mask) | |
img_padded = pipe( | |
prompt=text_prompt, | |
image=Image.fromarray(img_padded), | |
mask_image=Image.fromarray(255 - mask_padded), | |
num_inference_steps=step, | |
).images[0] | |
height, width, _ = img.shape | |
img_resized, mask_resized = recover_size( | |
np.array(img_padded), mask_padded, (height, width), padding_factors | |
) | |
mask_resized = np.expand_dims(mask_resized, -1) / 255 | |
img_resized = img_resized * (1 - mask_resized) + img * mask_resized | |
return img_resized | |
def setup_args(parser): | |
parser.add_argument( | |
"--input_img", | |
type=str, | |
required=True, | |
help="Path to a single input img", | |
) | |
parser.add_argument( | |
"--text_prompt", | |
type=str, | |
required=True, | |
help="Text prompt", | |
) | |
parser.add_argument( | |
"--input_mask_glob", | |
type=str, | |
required=True, | |
help="Glob to input masks", | |
) | |
parser.add_argument( | |
"--output_dir", | |
type=str, | |
required=True, | |
help="Output path to the directory with results.", | |
) | |
parser.add_argument( | |
"--seed", | |
type=int, | |
help="Specify seed for reproducibility.", | |
) | |
parser.add_argument( | |
"--deterministic", | |
action="store_true", | |
help="Use deterministic algorithms for reproducibility.", | |
) | |
if __name__ == "__main__": | |
"""Example usage: | |
python lama_inpaint.py \ | |
--input_img FA_demo/FA1_dog.png \ | |
--input_mask_glob "results/FA1_dog/mask*.png" \ | |
--text_prompt "a teddy bear on a bench" \ | |
--output_dir results | |
""" | |
parser = argparse.ArgumentParser() | |
setup_args(parser) | |
args = parser.parse_args(sys.argv[1:]) | |
device = "cuda" if torch.cuda.is_available() else "cpu" | |
if args.deterministic: | |
os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":4096:8" | |
torch.use_deterministic_algorithms(True) | |
img_stem = Path(args.input_img).stem | |
mask_ps = sorted(glob.glob(args.input_mask_glob)) | |
out_dir = Path(args.output_dir) / img_stem | |
out_dir.mkdir(parents=True, exist_ok=True) | |
img = load_img_to_array(args.input_img) | |
for mask_p in mask_ps: | |
if args.seed is not None: | |
torch.manual_seed(args.seed) | |
mask = load_img_to_array(mask_p) | |
img_filled_p = out_dir / f"filled_with_{Path(mask_p).name}" | |
img_filled = fill_img_with_sd(img, mask, args.text_prompt, device=device) | |
save_array_to_img(img_filled, img_filled_p) | |