Spaces:
openfree
/
Running on Zero

openfree commited on
Commit
218d678
โ€ข
1 Parent(s): 58583c5

Create app-backup-imgrate.py

Browse files
Files changed (1) hide show
  1. app-backup-imgrate.py +372 -0
app-backup-imgrate.py ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import spaces
3
+ import torch
4
+ from diffusers import AutoencoderKL, TCDScheduler
5
+ from diffusers.models.model_loading_utils import load_state_dict
6
+ from gradio_imageslider import ImageSlider
7
+ from huggingface_hub import hf_hub_download
8
+
9
+ from controlnet_union import ControlNetModel_Union
10
+ from pipeline_fill_sd_xl import StableDiffusionXLFillPipeline
11
+
12
+ from PIL import Image, ImageDraw
13
+ import numpy as np
14
+
15
+ config_file = hf_hub_download(
16
+ "xinsir/controlnet-union-sdxl-1.0",
17
+ filename="config_promax.json",
18
+ )
19
+
20
+ config = ControlNetModel_Union.load_config(config_file)
21
+ controlnet_model = ControlNetModel_Union.from_config(config)
22
+ model_file = hf_hub_download(
23
+ "xinsir/controlnet-union-sdxl-1.0",
24
+ filename="diffusion_pytorch_model_promax.safetensors",
25
+ )
26
+ state_dict = load_state_dict(model_file)
27
+ model, _, _, _, _ = ControlNetModel_Union._load_pretrained_model(
28
+ controlnet_model, state_dict, model_file, "xinsir/controlnet-union-sdxl-1.0"
29
+ )
30
+ model.to(device="cuda", dtype=torch.float16)
31
+
32
+ vae = AutoencoderKL.from_pretrained(
33
+ "madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16
34
+ ).to("cuda")
35
+
36
+ pipe = StableDiffusionXLFillPipeline.from_pretrained(
37
+ "SG161222/RealVisXL_V5.0_Lightning",
38
+ torch_dtype=torch.float16,
39
+ vae=vae,
40
+ controlnet=model,
41
+ variant="fp16",
42
+ ).to("cuda")
43
+
44
+ pipe.scheduler = TCDScheduler.from_config(pipe.scheduler.config)
45
+
46
+
47
+ def can_expand(source_width, source_height, target_width, target_height, alignment):
48
+ """Checks if the image can be expanded based on the alignment."""
49
+ if alignment in ("Left", "Right") and source_width >= target_width:
50
+ return False
51
+ if alignment in ("Top", "Bottom") and source_height >= target_height:
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_size, prompt_input=None, alignment="Middle"):
57
+ source = image
58
+ target_size = (width, height)
59
+ overlap = overlap_width
60
+
61
+ # Upscale if source is smaller than target in both dimensions
62
+ if source.width < target_size[0] and source.height < target_size[1]:
63
+ scale_factor = min(target_size[0] / source.width, target_size[1] / source.height)
64
+ new_width = int(source.width * scale_factor)
65
+ new_height = int(source.height * scale_factor)
66
+ source = source.resize((new_width, new_height), Image.LANCZOS)
67
+
68
+ if source.width > target_size[0] or source.height > target_size[1]:
69
+ scale_factor = min(target_size[0] / source.width, target_size[1] / source.height)
70
+ new_width = int(source.width * scale_factor)
71
+ new_height = int(source.height * scale_factor)
72
+ source = source.resize((new_width, new_height), Image.LANCZOS)
73
+
74
+ if resize_option == "Full":
75
+ resize_size = max(source.width, source.height)
76
+ elif resize_option == "1/2":
77
+ resize_size = max(source.width, source.height) // 2
78
+ elif resize_option == "1/3":
79
+ resize_size = max(source.width, source.height) // 3
80
+ elif resize_option == "1/4":
81
+ resize_size = max(source.width, source.height) // 4
82
+ else: # Custom
83
+ resize_size = custom_resize_size
84
+
85
+ aspect_ratio = source.height / source.width
86
+ new_width = resize_size
87
+ new_height = int(resize_size * aspect_ratio)
88
+ source = source.resize((new_width, new_height), Image.LANCZOS)
89
+
90
+ if not can_expand(source.width, source.height, target_size[0], target_size[1], alignment):
91
+ alignment = "Middle"
92
+
93
+ # Calculate margins based on alignment
94
+ if alignment == "Middle":
95
+ margin_x = (target_size[0] - source.width) // 2
96
+ margin_y = (target_size[1] - source.height) // 2
97
+ elif alignment == "Left":
98
+ margin_x = 0
99
+ margin_y = (target_size[1] - source.height) // 2
100
+ elif alignment == "Right":
101
+ margin_x = target_size[0] - source.width
102
+ margin_y = (target_size[1] - source.height) // 2
103
+ elif alignment == "Top":
104
+ margin_x = (target_size[0] - source.width) // 2
105
+ margin_y = 0
106
+ elif alignment == "Bottom":
107
+ margin_x = (target_size[0] - source.width) // 2
108
+ margin_y = target_size[1] - source.height
109
+
110
+ background = Image.new('RGB', target_size, (255, 255, 255))
111
+ background.paste(source, (margin_x, margin_y))
112
+
113
+ mask = Image.new('L', target_size, 255)
114
+ mask_draw = ImageDraw.Draw(mask)
115
+
116
+ # Adjust mask generation based on alignment
117
+ if alignment == "Middle":
118
+ mask_draw.rectangle([
119
+ (margin_x + overlap, margin_y + overlap),
120
+ (margin_x + source.width - overlap, margin_y + source.height - overlap)
121
+ ], fill=0)
122
+ elif alignment == "Left":
123
+ mask_draw.rectangle([
124
+ (margin_x, margin_y),
125
+ (margin_x + source.width - overlap, margin_y + source.height)
126
+ ], fill=0)
127
+ elif alignment == "Right":
128
+ mask_draw.rectangle([
129
+ (margin_x + overlap, margin_y),
130
+ (margin_x + source.width, margin_y + source.height)
131
+ ], fill=0)
132
+ elif alignment == "Top":
133
+ mask_draw.rectangle([
134
+ (margin_x, margin_y),
135
+ (margin_x + source.width, margin_y + source.height - overlap)
136
+ ], fill=0)
137
+ elif alignment == "Bottom":
138
+ mask_draw.rectangle([
139
+ (margin_x, margin_y + overlap),
140
+ (margin_x + source.width, margin_y + source.height)
141
+ ], fill=0)
142
+
143
+ cnet_image = background.copy()
144
+ cnet_image.paste(0, (0, 0), mask)
145
+
146
+ final_prompt = f"{prompt_input} , high quality, 4k"
147
+
148
+ (
149
+ prompt_embeds,
150
+ negative_prompt_embeds,
151
+ pooled_prompt_embeds,
152
+ negative_pooled_prompt_embeds,
153
+ ) = pipe.encode_prompt(final_prompt, "cuda", True)
154
+
155
+ for image in pipe(
156
+ prompt_embeds=prompt_embeds,
157
+ negative_prompt_embeds=negative_prompt_embeds,
158
+ pooled_prompt_embeds=pooled_prompt_embeds,
159
+ negative_pooled_prompt_embeds=negative_pooled_prompt_embeds,
160
+ image=cnet_image,
161
+ num_inference_steps=num_inference_steps
162
+ ):
163
+ yield cnet_image, image
164
+
165
+ image = image.convert("RGBA")
166
+ cnet_image.paste(image, (0, 0), mask)
167
+
168
+ yield background, cnet_image
169
+
170
+ def clear_result():
171
+ """Clears the result ImageSlider."""
172
+ return gr.update(value=None)
173
+
174
+ def preload_presets(target_ratio, ui_width, ui_height):
175
+ """Updates the width and height sliders based on the selected aspect ratio."""
176
+ if target_ratio == "9:16":
177
+ changed_width = 720
178
+ changed_height = 1280
179
+ return changed_width, changed_height, gr.update(open=False)
180
+ elif target_ratio == "16:9":
181
+ changed_width = 1280
182
+ changed_height = 720
183
+ return changed_width, changed_height, gr.update(open=False)
184
+ elif target_ratio == "1:1":
185
+ changed_width = 1024
186
+ changed_height = 1024
187
+ return changed_width, changed_height, gr.update(open=False)
188
+ elif target_ratio == "Custom":
189
+ return ui_width, ui_height, gr.update(open=True)
190
+
191
+ def select_the_right_preset(user_width, user_height):
192
+ if user_width == 720 and user_height == 1280:
193
+ return "9:16"
194
+ elif user_width == 1280 and user_height == 720:
195
+ return "16:9"
196
+ elif user_width == 1024 and user_height == 1024:
197
+ return "1:1"
198
+ else:
199
+ return "Custom"
200
+
201
+ def toggle_custom_resize_slider(resize_option):
202
+ return gr.update(visible=(resize_option == "Custom"))
203
+
204
+ css = """
205
+ footer {
206
+ visibility: hidden;
207
+ }
208
+ """
209
+
210
+
211
+
212
+ with gr.Blocks(theme="Nymbo/Nymbo_Theme", css=css) as demo:
213
+ with gr.Column():
214
+
215
+
216
+ with gr.Row():
217
+ with gr.Column():
218
+ input_image = gr.Image(
219
+ type="pil",
220
+ label="Input Image"
221
+ )
222
+
223
+ with gr.Row():
224
+ with gr.Column(scale=2):
225
+ prompt_input = gr.Textbox(label="Prompt (Optional)")
226
+ with gr.Column(scale=1):
227
+ run_button = gr.Button("Generate")
228
+
229
+ with gr.Row():
230
+ target_ratio = gr.Radio(
231
+ label="Expected Ratio",
232
+ choices=["9:16", "16:9", "1:1", "Custom"],
233
+ value="9:16",
234
+ scale=2
235
+ )
236
+
237
+ alignment_dropdown = gr.Dropdown(
238
+ choices=["Middle", "Left", "Right", "Top", "Bottom"],
239
+ value="Middle",
240
+ label="๊ณ ์ • ์œ„์น˜ ์„ ํƒ"
241
+ )
242
+
243
+ with gr.Accordion(label="Advanced settings", open=False) as settings_panel:
244
+ with gr.Column():
245
+ with gr.Row():
246
+ width_slider = gr.Slider(
247
+ label="Width",
248
+ minimum=256,
249
+ maximum=1536,
250
+ step=8,
251
+ value=720, # Set a default value
252
+ )
253
+ height_slider = gr.Slider(
254
+ label="Height",
255
+ minimum=256,
256
+ maximum=1536,
257
+ step=8,
258
+ value=480, # Set a default value
259
+ )
260
+ with gr.Row():
261
+ num_inference_steps = gr.Slider(label="Steps", minimum=4, maximum=12, step=1, value=8)
262
+ overlap_width = gr.Slider(
263
+ label="Mask overlap width",
264
+ minimum=1,
265
+ maximum=50,
266
+ value=42,
267
+ step=1
268
+ )
269
+ with gr.Row():
270
+ resize_option = gr.Radio(
271
+ label="Resize input image",
272
+ choices=["Full", "1/2", "1/3", "1/4", "Custom"],
273
+ value="Full"
274
+ )
275
+
276
+ custom_resize_size = gr.Slider(
277
+ label="Custom resize size",
278
+ minimum=256, # ์ด์ „์—๋Š” 720์ด์—ˆ์Šต๋‹ˆ๋‹ค.
279
+ maximum=1024,
280
+ step=8,
281
+ value=512, # ์ดˆ๊ธฐ ๊ฐ’์ด๋ฏ€๋กœ ์ด ๊ฐ’๋„ ์ ์ ˆํžˆ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
282
+ visible=False # ๊ธฐ๋ณธ์ ์œผ๋กœ ์ด ์Šฌ๋ผ์ด๋”๋Š” ์ˆจ๊ฒจ์ ธ ์žˆ์œผ๋ฉฐ, 'Custom'์ด ์„ ํƒ๋  ๋•Œ๋งŒ ๋ณด์ž…๋‹ˆ๋‹ค.
283
+ )
284
+
285
+
286
+
287
+ gr.Examples(
288
+ examples=[
289
+ ["./examples/example_2.jpg", 1440, 810, "Middle"],
290
+ ["./examples/example_3.jpg", 1024, 1024, "Bottom"],
291
+ ["./examples/example_4.png", 1024, 1024, "Top"],
292
+ ],
293
+ inputs=[input_image, width_slider, height_slider, alignment_dropdown],
294
+ )
295
+
296
+ with gr.Column():
297
+ result = ImageSlider(
298
+ interactive=False,
299
+ label="Generated Image",
300
+ )
301
+ use_as_input_button = gr.Button("Use as Input Image", visible=False)
302
+
303
+ def use_output_as_input(output_image):
304
+ """Sets the generated output as the new input image."""
305
+ return gr.update(value=output_image[1])
306
+
307
+ use_as_input_button.click(
308
+ fn=use_output_as_input,
309
+ inputs=[result],
310
+ outputs=[input_image]
311
+ )
312
+
313
+ target_ratio.change(
314
+ fn=preload_presets,
315
+ inputs=[target_ratio, width_slider, height_slider],
316
+ outputs=[width_slider, height_slider, settings_panel],
317
+ queue=False
318
+ )
319
+
320
+ width_slider.change(
321
+ fn=select_the_right_preset,
322
+ inputs=[width_slider, height_slider],
323
+ outputs=[target_ratio],
324
+ queue=False
325
+ )
326
+
327
+ height_slider.change(
328
+ fn=select_the_right_preset,
329
+ inputs=[width_slider, height_slider],
330
+ outputs=[target_ratio],
331
+ queue=False
332
+ )
333
+
334
+ resize_option.change(
335
+ fn=toggle_custom_resize_slider,
336
+ inputs=[resize_option],
337
+ outputs=[custom_resize_size],
338
+ queue=False
339
+ )
340
+
341
+ run_button.click(
342
+ fn=clear_result,
343
+ inputs=None,
344
+ outputs=result,
345
+ ).then(
346
+ fn=infer,
347
+ inputs=[input_image, width_slider, height_slider, overlap_width, num_inference_steps,
348
+ resize_option, custom_resize_size, prompt_input, alignment_dropdown],
349
+ outputs=result,
350
+ ).then(
351
+ fn=lambda: gr.update(visible=True),
352
+ inputs=None,
353
+ outputs=use_as_input_button,
354
+ )
355
+
356
+ prompt_input.submit(
357
+ fn=clear_result,
358
+ inputs=None,
359
+ outputs=result,
360
+ ).then(
361
+ fn=infer,
362
+ inputs=[input_image, width_slider, height_slider, overlap_width, num_inference_steps,
363
+ resize_option, custom_resize_size, prompt_input, alignment_dropdown],
364
+ outputs=result,
365
+ ).then(
366
+ fn=lambda: gr.update(visible=True),
367
+ inputs=None,
368
+ outputs=use_as_input_button,
369
+ )
370
+
371
+
372
+ demo.queue(max_size=12).launch(share=False)