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.

![image/jpeg](https://huggingface.co/rkv1990/FLUX.1-Fill-dev-outpainting/resolve/main/beauty-products.png)
![image/jpeg](https://huggingface.co/rkv1990/FLUX.1-Fill-dev-outpainting/resolve/main/beauty-products-mask.png)
![image/jpeg](https://huggingface.co/rkv1990/FLUX.1-Fill-dev-outpainting/resolve/main/flux-fill-dev.png)


## 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