rishh76 commited on
Commit
0c1bd79
·
verified ·
1 Parent(s): e967c3d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +154 -0
app.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Tuple, Dict
2
+ import requests
3
+ import random
4
+ import numpy as np
5
+ import gradio as gr
6
+ import torch
7
+ from PIL import Image
8
+ from diffusers import StableDiffusionInpaintPipeline
9
+
10
+ INFO = """
11
+ # FLUX-Based Inpainting 🎨
12
+
13
+ This interface utilizes a FLUX model variant for precise inpainting. Special thanks to the [Black Forest Labs](https://huggingface.co/black-forest-labs) team
14
+ and [Gothos](https://github.com/Gothos) for contributing to this advanced solution.
15
+ """
16
+
17
+ # Constants
18
+ MAX_SEED_VALUE = np.iinfo(np.int32).max
19
+ TARGET_DIM = 1024
20
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
21
+
22
+ # Function to clear background
23
+ def clear_background(image: Image.Image, threshold: int = 50) -> Image.Image:
24
+ image = image.convert("RGBA")
25
+ pixels = image.getdata()
26
+ processed_data = [
27
+ (0, 0, 0, 0) if sum(pixel[:3]) / 3 < threshold else pixel for pixel in pixels
28
+ ]
29
+ image.putdata(processed_data)
30
+ return image
31
+
32
+ # Sample data examples
33
+ EXAMPLES = [
34
+ [
35
+ {
36
+ "background": Image.open(requests.get("https://example.com/doge-1.png", stream=True).raw),
37
+ "layers": [clear_background(Image.open(requests.get("https://example.com/mask-1.png", stream=True).raw))],
38
+ "composite": Image.open(requests.get("https://example.com/composite-1.png", stream=True).raw),
39
+ },
40
+ "desert mirage",
41
+ 42,
42
+ False,
43
+ 0.75,
44
+ 25
45
+ ],
46
+ [
47
+ {
48
+ "background": Image.open(requests.get("https://example.com/doge-2.png", stream=True).raw),
49
+ "layers": [clear_background(Image.open(requests.get("https://example.com/mask-2.png", stream=True).raw))],
50
+ "composite": Image.open(requests.get("https://example.com/composite-2.png", stream=True).raw),
51
+ },
52
+ "neon city",
53
+ 100,
54
+ True,
55
+ 0.9,
56
+ 35
57
+ ]
58
+ ]
59
+
60
+ # Load model
61
+ inpainting_pipeline = StableDiffusionInpaintPipeline.from_pretrained(
62
+ "black-forest-labs/FLUX.1-schnell", torch_dtype=torch.bfloat16).to(DEVICE)
63
+
64
+ # Utility to adjust image size
65
+ def get_scaled_dimensions(
66
+ original_size: Tuple[int, int], max_dim: int = TARGET_DIM
67
+ ) -> Tuple[int, int]:
68
+ width, height = original_size
69
+ scaling_factor = max_dim / max(width, height)
70
+ return (int(width * scaling_factor) // 32 * 32, int(height * scaling_factor) // 32 * 32)
71
+
72
+ @spaces.GPU(duration=100)
73
+ def generate_inpainting(
74
+ input_data: Dict,
75
+ prompt_text: str,
76
+ chosen_seed: int,
77
+ use_random_seed: bool,
78
+ inpainting_strength: float,
79
+ steps: int,
80
+ progress=gr.Progress(track_tqdm=True)
81
+ ):
82
+ if not prompt_text:
83
+ return gr.Info("Provide a prompt to proceed."), None
84
+
85
+ background = input_data.get("background")
86
+ mask_layer = input_data.get("layers")[0]
87
+
88
+ if not background:
89
+ return gr.Info("Background image is missing."), None
90
+
91
+ if not mask_layer:
92
+ return gr.Info("Mask layer is missing."), None
93
+
94
+ new_width, new_height = get_scaled_dimensions(background.size)
95
+ resized_background = background.resize((new_width, new_height), Image.LANCZOS)
96
+ resized_mask = mask_layer.resize((new_width, new_height), Image.LANCZOS)
97
+
98
+ if use_random_seed:
99
+ chosen_seed = random.randint(0, MAX_SEED_VALUE)
100
+
101
+ torch.manual_seed(chosen_seed)
102
+ generated_image = inpainting_pipeline(
103
+ prompt=prompt_text,
104
+ image=resized_background,
105
+ mask_image=resized_mask,
106
+ strength=inpainting_strength,
107
+ num_inference_steps=steps,
108
+ ).images[0]
109
+
110
+ return generated_image, resized_mask
111
+
112
+ # Build the Gradio interface
113
+ with gr.Blocks() as flux_app:
114
+ gr.Markdown(INFO)
115
+
116
+ with gr.Row():
117
+ with gr.Column():
118
+ image_editor = gr.ImageEditor(
119
+ label="Edit Image",
120
+ type="pil",
121
+ sources=["upload", "webcam"],
122
+ brush=gr.Brush(colors=["#FFF"], color_mode="fixed")
123
+ )
124
+
125
+ prompt_box = gr.Text(
126
+ label="Inpainting Prompt", placeholder="Describe the change you'd like."
127
+ )
128
+ run_button = gr.Button(value="Run Inpainting")
129
+
130
+ with gr.Accordion("Settings"):
131
+ seed_slider = gr.Slider(0, MAX_SEED_VALUE, step=1, value=42, label="Seed")
132
+ random_seed_toggle = gr.Checkbox(label="Randomize Seed", value=True)
133
+ inpainting_strength_slider = gr.Slider(0.0, 1.0, step=0.01, value=0.85, label="Inpainting Strength")
134
+ steps_slider = gr.Slider(1, 50, step=1, value=25, label="Inference Steps")
135
+
136
+ with gr.Column():
137
+ output_image = gr.Image(label="Output Image")
138
+ output_mask = gr.Image(label="Processed Mask")
139
+
140
+ run_button.click(
141
+ generate_inpainting,
142
+ inputs=[image_editor, prompt_box, seed_slider, random_seed_toggle, inpainting_strength_slider, steps_slider],
143
+ outputs=[output_image, output_mask]
144
+ )
145
+
146
+ gr.Examples(
147
+ examples=EXAMPLES,
148
+ fn=generate_inpainting,
149
+ inputs=[image_editor, prompt_box, seed_slider, random_seed_toggle, inpainting_strength_slider, steps_slider],
150
+ outputs=[output_image, output_mask],
151
+ run_on_click=True,
152
+ )
153
+
154
+ flux_app.launch(debug=False, show_error=True)