File size: 5,935 Bytes
5e9179b 91ad0bc 5e9179b 39f2dd2 f6ef36b 39f2dd2 8167243 567a310 f6ef36b 567a310 abb2c35 567a310 abb2c35 567a310 abb2c35 d00f5f1 abb2c35 d00f5f1 abb2c35 4abb129 abb2c35 4abb129 c312091 64b419f abb2c35 4abb129 abb2c35 c312091 10d66d5 abb2c35 567a310 91ad0bc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
---
language:
- en
base_model:
- black-forest-labs/FLUX.1-Fill-dev
pipeline_tag: text-to-image
library_name: diffusers
tags:
- outpainting
- inpainting
- flux
- diffusion
---
`FLUX.1 Fill [dev]` is a 12 billion parameter rectified flow transformer capable of filling areas in existing images based on a text description.
The idea is to unlock the full outpainting potential of Flux.1.Fill-dev model.
The original model parameters have not been finetuned or modified.
Rather, this simple hack unlocks the full potential of the Flux.1-Fill-dev model.
This is based on Flux.1-Fill-dev model and follows the FLUX.1-dev Non-Commercial License
https://github.com/black-forest-labs/flux/blob/main/model_licenses/LICENSE-FLUX1-dev is applicable.



## Diffusers
To use `FLUX.1 Fill [dev]` with the 🧨 diffusers python library, first install or upgrade diffusers
```shell
pip install -U diffusers
```
Then you can use `FluxFillPipeline` to run the model
Here is a code snippet to use the code.
```python
import numpy as np
import cv2
from PIL import Image
import torch
from diffusers import FluxFillPipeline
from diffusers.utils import load_image
from typing import Union
def prepare_masked_image(
foreground: Union[Image.Image, np.ndarray],
mask: Union[Image.Image, np.ndarray],
alpha: float = 0.001,
blur: bool = True
) -> Image.Image:
"""
Combines the foreground and mask to produce a masked image with noise in the masked region.
Args:
foreground (PIL.Image.Image or np.ndarray): The input image to be inpainted.
mask (PIL.Image.Image or np.ndarray): A binary mask (0 or 255) indicating the foreground region.
alpha (float): Blending factor for noise. Lower alpha → more noise in the masked area.
blur (bool): Whether to blur the randomly generated noise.
Returns:
PIL.Image.Image: The resulting masked image with noise in the masked area.
"""
# Ensure foreground is an ndarray
if isinstance(foreground, Image.Image):
foreground_np = np.array(foreground)
else:
foreground_np = foreground # assume already a NumPy array
# Ensure mask is a NumPy array and single-channel
if isinstance(mask, Image.Image):
mask_np = np.array(mask.convert("L")) # convert to grayscale
else:
mask_np = mask
if mask_np.ndim == 3:
mask_np = cv2.cvtColor(mask_np, cv2.COLOR_BGR2GRAY)
h, w, c = foreground_np.shape # height, width, channels
# Create 3×3 kernel for dilation (used later)
kernel = np.ones((3, 3), np.uint8)
# Generate random Gaussian noise
noise = np.random.rand(h, w) * 255
noise = noise.astype(np.uint8)
if blur:
noise = cv2.GaussianBlur(noise, (5, 5), 0)
# Stack to 3 channels
noise_rgb = np.stack([noise, noise, noise], axis=-1)
# Prepare a black background
black_bg = np.zeros_like(foreground_np, dtype=np.uint8)
# Dilate the mask to get smoother boundaries for seamlessClone
dilated_mask = cv2.dilate(mask_np, kernel, iterations=10)
# Compute center for seamlessClone (center of the image)
center = (w // 2, h // 2)
# Use mixed clone to merge the foreground onto a black background, using the dilated mask
cloned = cv2.seamlessClone(
src=foreground_np,
dst=black_bg,
mask=dilated_mask,
p=center,
flags=cv2.MIXED_CLONE
)
# Blend cloned result (mostly black except where mask is) with noise
noisy_bg = (alpha * cloned + (1 - alpha) * noise_rgb).astype(np.uint8)
# Normalize mask to [0,1] float if it’s in [0,255]
if mask_np.max() <= 1:
mask_norm = mask_np.astype(np.float32)
else:
mask_norm = (mask_np / 255.0).astype(np.float32)
# Expand mask to 3 channels if needed
if mask_norm.ndim == 2:
mask_norm = np.stack([mask_norm] * 3, axis=-1)
# Combine: keep original pixels where mask=0, use noisy_bg where mask=1
combined = ((1 - mask_norm) * noisy_bg + mask_norm * foreground_np).astype(np.uint8)
return Image.fromarray(combined)
def main():
"""Entry point for running the FluxFill pipeline."""
# Load input image and its corresponding mask
fg_mask = load_image("https://huggingface.co/rkv1990/FLUX.1-Fill-dev-outpainting/resolve/main/beauty-products-mask.png").convert("L")
input_image= load_image("https://huggingface.co/rkv1990/FLUX.1-Fill-dev-outpainting/resolve/main/beauty-products.png").convert("RGB")
inpaint_mask = np.array(255-np.array(fg_mask))
w,h = input_image.size
masked_image = prepare_masked_image(foreground=input_image, mask=fg_mask)
# Initialize the FluxFill pipeline
pipe = FluxFillPipeline.from_pretrained(
"black-forest-labs/FLUX.1-Fill-dev",
torch_dtype=torch.bfloat16
).to("cuda")
# Run the pipeline
output = pipe(
prompt="A mist-covered forest at dawn, with pale golden light filtering through ancient, twisted trees. Soft fog swirls around delicate wildflowers glowing faintly with bioluminescence.",
image=masked_image,
mask_image=inpaint_mask,
height=h,
width=w,
guidance_scale=30,
num_inference_steps=50,
max_sequence_length=512,
generator=torch.Generator(device="cpu").manual_seed(0)
).images[0]
# Save the resulting image
output.save("flux-fill-dev.png")
print("Saved output to flux-fill-dev.png")
if __name__ == "__main__":
main()
```
To learn more check out the [diffusers](https://huggingface.co/docs/diffusers/main/en/api/pipelines/flux) documentation |