vilarin commited on
Commit
cd3265c
·
verified ·
1 Parent(s): 4e093d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +81 -49
app.py CHANGED
@@ -75,15 +75,67 @@ def inpaintGen(
75
  return result, seed
76
 
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  @spaces.GPU()
80
  def outpaintGen(
81
  img,
82
  outpaint_prompt: str,
83
- overlap_top: int,
84
- overlap_right: int,
85
- overlap_bottom: int,
86
- overlap_left: int,
 
 
87
  op_guidance: float,
88
  op_num_steps: int,
89
  op_seed: int,
@@ -91,43 +143,18 @@ def outpaintGen(
91
  ):
92
  image = Image.open(img)
93
 
94
- # Convert input to PIL Image if it's a numpy array
95
- if isinstance(image, np.ndarray):
96
- image = Image.fromarray(image)
 
 
 
 
 
 
97
 
98
- # Get original dimensions
99
- original_width, original_height = image.size
100
 
101
- # Calculate new dimensions
102
- new_width = original_width + overlap_left + overlap_right
103
- new_height = original_height + overlap_top + overlap_bottom
104
-
105
- # Create new blank mask image (black background)
106
- mask_image = Image.new('RGB', (new_width, new_height), color='black')
107
-
108
- # Create white rectangle for original image area
109
- white_area = Image.new('RGB', (original_width, original_height), color='white')
110
-
111
- # Paste white rectangle at the appropriate position
112
- mask_image.paste(white_area, (overlap_left, overlap_top))
113
-
114
- # Create a new image with the same size as the original image
115
- new_image = Image.new('RGB', (new_width, new_height), color='black')
116
-
117
- # Paste the original image onto the new image
118
- new_image.paste(image, (overlap_left, overlap_top))
119
-
120
- # Convert to grayscale
121
- mask_image = mask_image.convert('L')
122
- mask_image = Image.eval(mask_image, lambda x: 255 - x)
123
-
124
- fix_width = (new_width // 16) * 16
125
- fix_height = (new_height // 16) * 16
126
-
127
- # If the image size is not already divisible by 16, resize it
128
- # if new_width != fix_width or new_height != fix_height:
129
- # mask_image = mask_image.resize((fix_width, fix_height), Image.LANCZOS)
130
-
131
  if op_randomize_seed:
132
  op_seed = random.randint(0, MAX_SEED)
133
  generator = torch.Generator("cpu").manual_seed(op_seed)
@@ -136,8 +163,8 @@ def outpaintGen(
136
  prompt=outpaint_prompt,
137
  image=new_image,
138
  mask_image=mask_image,
139
- width=fix_width,
140
- height=fix_height,
141
  num_inference_steps=op_num_steps,
142
  generator=generator,
143
  guidance_scale=op_guidance,
@@ -198,11 +225,14 @@ with gr.Blocks(theme="ocean", title="Flux.1 Fill dev", css=CSS) as demo:
198
  outpaint_clearBtn = gr.ClearButton([img, outpaint_prompt], value="Clear")
199
  image_exp = gr.Image(type="pil", label="Output", height=960)
200
  with gr.Accordion("Advanced ⚙️", open=False):
 
 
 
 
 
201
  with gr.Row():
202
- overlap_top = gr.Number(label="Top", value=64, precision=0)
203
- overlap_right = gr.Number(label="Right", value=64, precision=0)
204
- overlap_bottom = gr.Number(label="Bottom", value=64, precision=0)
205
- overlap_left = gr.Number(label="Left", value=64, precision=0)
206
  op_guidance = gr.Slider(label="Guidance scale", minimum=1, maximum=50, value=30.0, step=0.1)
207
  op_num_steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=20, step=1)
208
  op_seed = gr.Number(label="Seed", value=42, precision=0)
@@ -217,10 +247,12 @@ with gr.Blocks(theme="ocean", title="Flux.1 Fill dev", css=CSS) as demo:
217
  inputs = [
218
  img,
219
  outpaint_prompt,
220
- overlap_top,
221
- overlap_right,
222
- overlap_bottom,
223
- overlap_left,
 
 
224
  op_guidance,
225
  op_num_steps,
226
  op_seed,
 
75
  return result, seed
76
 
77
 
78
+ def add_border_and_mask(image, zoom_all=1.0, zoom_left=0, zoom_right=0, zoom_up=0, zoom_down=0, overlap=0.01):
79
+ """Adds a black border around the image with individual side control and mask overlap"""
80
+ orig_width, orig_height = image.size
81
+
82
+ # Calculate padding for each side (in pixels)
83
+ left_pad = int(orig_width * zoom_left)
84
+ right_pad = int(orig_width * zoom_right)
85
+ top_pad = int(orig_height * zoom_up)
86
+ bottom_pad = int(orig_height * zoom_down)
87
+
88
+ # Calculate overlap in pixels
89
+ overlap_left = int(orig_width * overlap)
90
+ overlap_right = int(orig_width * overlap)
91
+ overlap_top = int(orig_height * overlap)
92
+ overlap_bottom = int(orig_height * overlap)
93
+
94
+ # If using the all-sides zoom, add it to each side
95
+ if zoom_all > 1.0:
96
+ extra_each_side = (zoom_all - 1.0) / 2
97
+ left_pad += int(orig_width * extra_each_side)
98
+ right_pad += int(orig_width * extra_each_side)
99
+ top_pad += int(orig_height * extra_each_side)
100
+ bottom_pad += int(orig_height * extra_each_side)
101
+
102
+ # Calculate new dimensions (ensure they're multiples of 32)
103
+ new_width = 32 * round((orig_width + left_pad + right_pad) / 32)
104
+ new_height = 32 * round((orig_height + top_pad + bottom_pad) / 32)
105
+
106
+ # Create new image with black border
107
+ bordered_image = Image.new("RGB", (new_width, new_height), (0, 0, 0))
108
+ # Paste original image in position
109
+ paste_x = left_pad
110
+ paste_y = top_pad
111
+ bordered_image.paste(image, (paste_x, paste_y))
112
+
113
+ # Create mask (white where the border is, black where the original image was)
114
+ mask = Image.new("L", (new_width, new_height), 255) # White background
115
+ # Paste black rectangle with overlap adjustment
116
+ mask.paste(
117
+ 0,
118
+ (
119
+ paste_x + overlap_left, # Left edge moves right
120
+ paste_y + overlap_top, # Top edge moves down
121
+ paste_x + orig_width - overlap_right, # Right edge moves left
122
+ paste_y + orig_height - overlap_bottom, # Bottom edge moves up
123
+ ),
124
+ )
125
+
126
+ return bordered_image, mask
127
+
128
 
129
  @spaces.GPU()
130
  def outpaintGen(
131
  img,
132
  outpaint_prompt: str,
133
+ overlap: float,
134
+ zoom_all: float,
135
+ zoom_left: float,
136
+ zoom_right: float,
137
+ zoom_up: float,
138
+ zoom_down: float,
139
  op_guidance: float,
140
  op_num_steps: int,
141
  op_seed: int,
 
143
  ):
144
  image = Image.open(img)
145
 
146
+ new_image, mask_image = add_border_and_mask(
147
+ image,
148
+ zoom_all=zoom_all,
149
+ zoom_left=zoom_left,
150
+ zoom_right=zoom_right,
151
+ zoom_up=zoom_up,
152
+ zoom_down=zoom_down,
153
+ overlap=overlap,
154
+ )
155
 
156
+ width, height = new_image.size
 
157
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  if op_randomize_seed:
159
  op_seed = random.randint(0, MAX_SEED)
160
  generator = torch.Generator("cpu").manual_seed(op_seed)
 
163
  prompt=outpaint_prompt,
164
  image=new_image,
165
  mask_image=mask_image,
166
+ width=width,
167
+ height=height,
168
  num_inference_steps=op_num_steps,
169
  generator=generator,
170
  guidance_scale=op_guidance,
 
225
  outpaint_clearBtn = gr.ClearButton([img, outpaint_prompt], value="Clear")
226
  image_exp = gr.Image(type="pil", label="Output", height=960)
227
  with gr.Accordion("Advanced ⚙️", open=False):
228
+ overlap = gr.Slider(label="Overlap", minimum=0.01, maximum=0.25, value=0.01, step=0.01)
229
+ zoom_all = gr.Slider(label="Zoom Out Amount (All Sides)", minimum=1.0, maximum=3.0, value=1.0, step=0.1)
230
+ with gr.Row():
231
+ zoom_left = gr.Slider(label="Left", minimum=0.0, maximum=1.0, value=0.0, step=0.1)
232
+ zoom_right = gr.Slider(label="Right", minimum=0.0, maximum=1.0, value=0.0, step=0.1)
233
  with gr.Row():
234
+ zoom_up = gr.Slider(label="Up", minimum=0.0, maximum=1.0, value=0.0, step=0.1)
235
+ zoom_down = gr.Slider(label="Down", minimum=0.0, maximum=1.0, value=0.0, step=0.1)
 
 
236
  op_guidance = gr.Slider(label="Guidance scale", minimum=1, maximum=50, value=30.0, step=0.1)
237
  op_num_steps = gr.Slider(label="Steps", minimum=1, maximum=50, value=20, step=1)
238
  op_seed = gr.Number(label="Seed", value=42, precision=0)
 
247
  inputs = [
248
  img,
249
  outpaint_prompt,
250
+ overlap,
251
+ zoom_all,
252
+ zoom_left,
253
+ zoom_right,
254
+ zoom_up,
255
+ zoom_down,
256
  op_guidance,
257
  op_num_steps,
258
  op_seed,