fffiloni commited on
Commit
c6d3715
·
verified ·
1 Parent(s): c01d116

multiple changes, new preview mask and alignement

Browse files
Files changed (1) hide show
  1. app.py +92 -50
app.py CHANGED
@@ -52,19 +52,16 @@ def can_expand(source_width, source_height, target_width, target_height, alignme
52
  return False
53
  return True
54
 
55
- @spaces.GPU(duration=24)
56
- def infer(image, width, height, overlap_width, num_inference_steps, resize_option, custom_resize_percentage, prompt_input=None, alignment="Middle"):
57
- source = image
58
  target_size = (width, height)
59
- overlap = overlap_width
60
 
61
  # Calculate the scaling factor to fit the image within the target size
62
- scale_factor = min(target_size[0] / source.width, target_size[1] / source.height)
63
- new_width = int(source.width * scale_factor)
64
- new_height = int(source.height * scale_factor)
65
 
66
  # Resize the source image to fit within target size
67
- source = source.resize((new_width, new_height), Image.LANCZOS)
68
 
69
  # Apply resize option using percentages
70
  if resize_option == "Full":
@@ -90,6 +87,14 @@ def infer(image, width, height, overlap_width, num_inference_steps, resize_optio
90
  # Resize the image
91
  source = source.resize((new_width, new_height), Image.LANCZOS)
92
 
 
 
 
 
 
 
 
 
93
  # Calculate margins based on alignment
94
  if alignment == "Middle":
95
  margin_x = (target_size[0] - new_width) // 2
@@ -107,6 +112,10 @@ def infer(image, width, height, overlap_width, num_inference_steps, resize_optio
107
  margin_x = (target_size[0] - new_width) // 2
108
  margin_y = target_size[1] - new_height
109
 
 
 
 
 
110
  # Create a new background image and paste the resized source image
111
  background = Image.new('RGB', target_size, (255, 255, 255))
112
  background.paste(source, (margin_x, margin_y))
@@ -115,34 +124,43 @@ def infer(image, width, height, overlap_width, num_inference_steps, resize_optio
115
  mask = Image.new('L', target_size, 255)
116
  mask_draw = ImageDraw.Draw(mask)
117
 
118
- # Adjust mask generation based on alignment
119
- if alignment == "Middle":
120
- mask_draw.rectangle([
121
- (margin_x + overlap, margin_y + overlap),
122
- (margin_x + new_width - overlap, margin_y + new_height - overlap)
123
- ], fill=0)
124
- elif alignment == "Left":
125
- mask_draw.rectangle([
126
- (margin_x, margin_y),
127
- (margin_x + new_width - overlap, margin_y + new_height)
128
- ], fill=0)
129
- elif alignment == "Right":
130
- mask_draw.rectangle([
131
- (margin_x + overlap, margin_y),
132
- (margin_x + new_width, margin_y + new_height)
133
- ], fill=0)
134
- elif alignment == "Top":
135
- mask_draw.rectangle([
136
- (margin_x, margin_y),
137
- (margin_x + new_width, margin_y + new_height - overlap)
138
- ], fill=0)
139
- elif alignment == "Bottom":
140
- mask_draw.rectangle([
141
- (margin_x, margin_y + overlap),
142
- (margin_x + new_width, margin_y + new_height)
143
- ], fill=0)
 
 
 
 
 
144
 
145
- if not can_expand(source.width, source.height, target_size[0], target_size[1], alignment):
 
 
 
 
146
  alignment = "Middle"
147
 
148
  cnet_image = background.copy()
@@ -181,15 +199,15 @@ def preload_presets(target_ratio, ui_width, ui_height):
181
  if target_ratio == "9:16":
182
  changed_width = 720
183
  changed_height = 1280
184
- return changed_width, changed_height, gr.update(open=False)
185
  elif target_ratio == "16:9":
186
  changed_width = 1280
187
  changed_height = 720
188
- return changed_width, changed_height, gr.update(open=False)
189
  elif target_ratio == "1:1":
190
  changed_width = 1024
191
  changed_height = 1024
192
- return changed_width, changed_height, gr.update(open=False)
193
  elif target_ratio == "Custom":
194
  return ui_width, ui_height, gr.update(open=True)
195
 
@@ -265,28 +283,35 @@ with gr.Blocks(css=css) as demo:
265
  with gr.Column():
266
  with gr.Row():
267
  width_slider = gr.Slider(
268
- label="Width",
269
  minimum=720,
270
  maximum=1536,
271
  step=8,
272
  value=720, # Set a default value
273
  )
274
  height_slider = gr.Slider(
275
- label="Height",
276
  minimum=720,
277
  maximum=1536,
278
  step=8,
279
  value=1280, # Set a default value
280
  )
281
- with gr.Row():
282
- num_inference_steps = gr.Slider(label="Steps", minimum=4, maximum=12, step=1, value=8)
283
- overlap_width = gr.Slider(
284
- label="Mask overlap width",
 
285
  minimum=1,
286
  maximum=50,
287
- value=42,
288
  step=1
289
  )
 
 
 
 
 
 
290
  with gr.Row():
291
  resize_option = gr.Radio(
292
  label="Resize input image",
@@ -294,13 +319,17 @@ with gr.Blocks(css=css) as demo:
294
  value="Full"
295
  )
296
  custom_resize_percentage = gr.Slider(
297
- label="Custom resize percentage",
298
  minimum=1,
299
  maximum=100,
300
  step=1,
301
  value=50,
302
  visible=False
303
  )
 
 
 
 
304
 
305
  gr.Examples(
306
  examples=[
@@ -312,6 +341,8 @@ with gr.Blocks(css=css) as demo:
312
  inputs=[input_image, width_slider, height_slider, alignment_dropdown],
313
  )
314
 
 
 
315
  with gr.Column():
316
  result = ImageSlider(
317
  interactive=False,
@@ -320,6 +351,7 @@ with gr.Blocks(css=css) as demo:
320
  use_as_input_button = gr.Button("Use as Input Image", visible=False)
321
 
322
  history_gallery = gr.Gallery(label="History", columns=6, object_fit="contain", interactive=False)
 
323
 
324
 
325
 
@@ -367,8 +399,9 @@ with gr.Blocks(css=css) as demo:
367
  outputs=result,
368
  ).then( # Generate the new image
369
  fn=infer,
370
- inputs=[input_image, width_slider, height_slider, overlap_width, num_inference_steps,
371
- resize_option, custom_resize_percentage, prompt_input, alignment_dropdown],
 
372
  outputs=result,
373
  ).then( # Update the history gallery
374
  fn=lambda x, history: update_history(x[1], history),
@@ -386,8 +419,9 @@ with gr.Blocks(css=css) as demo:
386
  outputs=result,
387
  ).then( # Generate the new image
388
  fn=infer,
389
- inputs=[input_image, width_slider, height_slider, overlap_width, num_inference_steps,
390
- resize_option, custom_resize_percentage, prompt_input, alignment_dropdown],
 
391
  outputs=result,
392
  ).then( # Update the history gallery
393
  fn=lambda x, history: update_history(x[1], history),
@@ -399,4 +433,12 @@ with gr.Blocks(css=css) as demo:
399
  outputs=use_as_input_button,
400
  )
401
 
 
 
 
 
 
 
 
 
402
  demo.queue(max_size=12).launch(share=False)
 
52
  return False
53
  return True
54
 
55
+ def prepare_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom):
 
 
56
  target_size = (width, height)
 
57
 
58
  # Calculate the scaling factor to fit the image within the target size
59
+ scale_factor = min(target_size[0] / image.width, target_size[1] / image.height)
60
+ new_width = int(image.width * scale_factor)
61
+ new_height = int(image.height * scale_factor)
62
 
63
  # Resize the source image to fit within target size
64
+ source = image.resize((new_width, new_height), Image.LANCZOS)
65
 
66
  # Apply resize option using percentages
67
  if resize_option == "Full":
 
87
  # Resize the image
88
  source = source.resize((new_width, new_height), Image.LANCZOS)
89
 
90
+ # Calculate the overlap in pixels based on the percentage
91
+ overlap_x = int(new_width * (overlap_percentage / 100))
92
+ overlap_y = int(new_height * (overlap_percentage / 100))
93
+
94
+ # Ensure minimum overlap of 1 pixel
95
+ overlap_x = max(overlap_x, 1)
96
+ overlap_y = max(overlap_y, 1)
97
+
98
  # Calculate margins based on alignment
99
  if alignment == "Middle":
100
  margin_x = (target_size[0] - new_width) // 2
 
112
  margin_x = (target_size[0] - new_width) // 2
113
  margin_y = target_size[1] - new_height
114
 
115
+ # Adjust margins to eliminate gaps
116
+ margin_x = max(0, min(margin_x, target_size[0] - new_width))
117
+ margin_y = max(0, min(margin_y, target_size[1] - new_height))
118
+
119
  # Create a new background image and paste the resized source image
120
  background = Image.new('RGB', target_size, (255, 255, 255))
121
  background.paste(source, (margin_x, margin_y))
 
124
  mask = Image.new('L', target_size, 255)
125
  mask_draw = ImageDraw.Draw(mask)
126
 
127
+ # Calculate overlap areas
128
+ left_overlap = margin_x + overlap_x if overlap_left else margin_x
129
+ right_overlap = margin_x + new_width - overlap_x if overlap_right else margin_x + new_width
130
+ top_overlap = margin_y + overlap_y if overlap_top else margin_y
131
+ bottom_overlap = margin_y + new_height - overlap_y if overlap_bottom else margin_y + new_height
132
+
133
+ # Draw the mask
134
+ mask_draw.rectangle([
135
+ (left_overlap, top_overlap),
136
+ (right_overlap, bottom_overlap)
137
+ ], fill=0)
138
+
139
+ return background, mask
140
+
141
+ def preview_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom):
142
+ background, mask = prepare_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom)
143
+
144
+ # Create a preview image showing the mask
145
+ preview = background.copy().convert('RGBA')
146
+
147
+ # Create a semi-transparent red overlay
148
+ red_overlay = Image.new('RGBA', background.size, (255, 0, 0, 64)) # Reduced alpha to 64 (25% opacity)
149
+
150
+ # Convert black pixels in the mask to semi-transparent red
151
+ red_mask = Image.new('RGBA', background.size, (0, 0, 0, 0))
152
+ red_mask.paste(red_overlay, (0, 0), mask)
153
+
154
+ # Overlay the red mask on the background
155
+ preview = Image.alpha_composite(preview, red_mask)
156
+
157
+ return preview
158
 
159
+ @spaces.GPU(duration=24)
160
+ def infer(image, width, height, overlap_percentage, num_inference_steps, resize_option, custom_resize_percentage, prompt_input, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom):
161
+ background, mask = prepare_image_and_mask(image, width, height, overlap_percentage, resize_option, custom_resize_percentage, alignment, overlap_left, overlap_right, overlap_top, overlap_bottom)
162
+
163
+ if not can_expand(background.width, background.height, width, height, alignment):
164
  alignment = "Middle"
165
 
166
  cnet_image = background.copy()
 
199
  if target_ratio == "9:16":
200
  changed_width = 720
201
  changed_height = 1280
202
+ return changed_width, changed_height, gr.update()
203
  elif target_ratio == "16:9":
204
  changed_width = 1280
205
  changed_height = 720
206
+ return changed_width, changed_height, gr.update()
207
  elif target_ratio == "1:1":
208
  changed_width = 1024
209
  changed_height = 1024
210
+ return changed_width, changed_height, gr.update()
211
  elif target_ratio == "Custom":
212
  return ui_width, ui_height, gr.update(open=True)
213
 
 
283
  with gr.Column():
284
  with gr.Row():
285
  width_slider = gr.Slider(
286
+ label="Target Width",
287
  minimum=720,
288
  maximum=1536,
289
  step=8,
290
  value=720, # Set a default value
291
  )
292
  height_slider = gr.Slider(
293
+ label="Target Height",
294
  minimum=720,
295
  maximum=1536,
296
  step=8,
297
  value=1280, # Set a default value
298
  )
299
+
300
+ num_inference_steps = gr.Slider(label="Steps", minimum=4, maximum=12, step=1, value=8)
301
+ with gr.Group():
302
+ overlap_percentage = gr.Slider(
303
+ label="Mask overlap (%)",
304
  minimum=1,
305
  maximum=50,
306
+ value=10,
307
  step=1
308
  )
309
+ with gr.Row():
310
+ overlap_top = gr.Checkbox(label="Overlap Top", value=True)
311
+ overlap_right = gr.Checkbox(label="Overlap Right", value=True)
312
+ with gr.Row():
313
+ overlap_left = gr.Checkbox(label="Overlap Left", value=True)
314
+ overlap_bottom = gr.Checkbox(label="Overlap Bottom", value=True)
315
  with gr.Row():
316
  resize_option = gr.Radio(
317
  label="Resize input image",
 
319
  value="Full"
320
  )
321
  custom_resize_percentage = gr.Slider(
322
+ label="Custom resize (%)",
323
  minimum=1,
324
  maximum=100,
325
  step=1,
326
  value=50,
327
  visible=False
328
  )
329
+
330
+ with gr.Column():
331
+ preview_button = gr.Button("Preview alignment and mask")
332
+
333
 
334
  gr.Examples(
335
  examples=[
 
341
  inputs=[input_image, width_slider, height_slider, alignment_dropdown],
342
  )
343
 
344
+
345
+
346
  with gr.Column():
347
  result = ImageSlider(
348
  interactive=False,
 
351
  use_as_input_button = gr.Button("Use as Input Image", visible=False)
352
 
353
  history_gallery = gr.Gallery(label="History", columns=6, object_fit="contain", interactive=False)
354
+ preview_image = gr.Image(label="Preview")
355
 
356
 
357
 
 
399
  outputs=result,
400
  ).then( # Generate the new image
401
  fn=infer,
402
+ inputs=[input_image, width_slider, height_slider, overlap_percentage, num_inference_steps,
403
+ resize_option, custom_resize_percentage, prompt_input, alignment_dropdown,
404
+ overlap_left, overlap_right, overlap_top, overlap_bottom],
405
  outputs=result,
406
  ).then( # Update the history gallery
407
  fn=lambda x, history: update_history(x[1], history),
 
419
  outputs=result,
420
  ).then( # Generate the new image
421
  fn=infer,
422
+ inputs=[input_image, width_slider, height_slider, overlap_percentage, num_inference_steps,
423
+ resize_option, custom_resize_percentage, prompt_input, alignment_dropdown,
424
+ overlap_left, overlap_right, overlap_top, overlap_bottom],
425
  outputs=result,
426
  ).then( # Update the history gallery
427
  fn=lambda x, history: update_history(x[1], history),
 
433
  outputs=use_as_input_button,
434
  )
435
 
436
+ preview_button.click(
437
+ fn=preview_image_and_mask,
438
+ inputs=[input_image, width_slider, height_slider, overlap_percentage, resize_option, custom_resize_percentage, alignment_dropdown,
439
+ overlap_left, overlap_right, overlap_top, overlap_bottom],
440
+ outputs=preview_image,
441
+ queue=False
442
+ )
443
+
444
  demo.queue(max_size=12).launch(share=False)