Skip to content

Commit 5f740d0

Browse files
dg845williamberman
andauthored
[docs] Add inpainting example for forcing the unmasked area to remain unchanged to the docs (huggingface#4536)
* Initial code to add force_unmasked_unchanged argument to StableDiffusionInpaintPipeline.__call__. * Try to improve StableDiffusionInpaintPipelineFastTests.get_dummy_inputs. * Use original mask to preserve unmasked pixels in pixel space rather than latent space. * make style * start working on note in docs to force unmasked area to be unchanged * Add example of forcing the unmasked area to remain unchanged. * Revert "make style" This reverts commit fa77592. * Revert "Use original mask to preserve unmasked pixels in pixel space rather than latent space." This reverts commit 092bd0e. * Revert "Try to improve StableDiffusionInpaintPipelineFastTests.get_dummy_inputs." This reverts commit ff41cf4. * Revert "Initial code to add force_unmasked_unchanged argument to StableDiffusionInpaintPipeline.__call__." This reverts commit 9899797. --------- Co-authored-by: Will Berman <[email protected]>
1 parent 75f81c2 commit 5f740d0

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

docs/source/en/using-diffusers/inpaint.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,49 @@ Check out the Spaces below to try out image inpainting yourself!
7676
width="850"
7777
height="500"
7878
></iframe>
79+
80+
## Preserving the Unmasked Area of the Image
81+
82+
Generally speaking, [`StableDiffusionInpaintPipeline`] (and other inpainting pipelines) will change the unmasked part of the image as well. If this behavior is undesirable, you can force the unmasked area to remain the same as follows:
83+
84+
```python
85+
import PIL
86+
import numpy as np
87+
import torch
88+
89+
from diffusers import StableDiffusionInpaintPipeline
90+
from diffusers.utils import load_image
91+
92+
device = "cuda"
93+
pipeline = StableDiffusionInpaintPipeline.from_pretrained(
94+
"runwayml/stable-diffusion-inpainting",
95+
torch_dtype=torch.float16,
96+
)
97+
pipeline = pipeline.to(device)
98+
99+
img_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo.png"
100+
mask_url = "https://raw.githubusercontent.com/CompVis/latent-diffusion/main/data/inpainting_examples/overture-creations-5sI6fQgYIuo_mask.png"
101+
102+
init_image = load_image(img_url).resize((512, 512))
103+
mask_image = load_image(mask_url).resize((512, 512))
104+
105+
prompt = "Face of a yellow cat, high resolution, sitting on a park bench"
106+
repainted_image = pipeline(prompt=prompt, image=init_image, mask_image=mask_image).images[0]
107+
repainted_image.save("repainted_image.png")
108+
109+
# Convert mask to grayscale NumPy array
110+
mask_image_arr = np.array(mask_image.convert("L"))
111+
# Add a channel dimension to the end of the grayscale mask
112+
mask_image_arr = mask_image_arr[:, :, None]
113+
# Binarize the mask: 1s correspond to the pixels which are repainted
114+
mask_image_arr = mask_image_arr.astype(np.float32) / 255.0
115+
mask_image_arr[mask_image_arr < 0.5] = 0
116+
mask_image_arr[mask_image_arr >= 0.5] = 1
117+
118+
# Take the masked pixels from the repainted image and the unmasked pixels from the initial image
119+
unmasked_unchanged_image_arr = (1 - mask_image_arr) * init_image_arr + mask_image_arr * repainted_image_arr
120+
unmasked_unchanged_image = PIL.Image.fromarray(unmasked_unchanged_image_arr.round().astype("uint8"))
121+
unmasked_unchanged_image.save("force_unmasked_unchanged.png")
122+
```
123+
124+
Forcing the unmasked portion of the image to remain the same might result in some weird transitions between the unmasked and masked areas, since the model will typically change the masked and unmasked areas to make the transition more natural.

0 commit comments

Comments
 (0)