fantos commited on
Commit
6891a4e
·
verified ·
1 Parent(s): edecb65

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -223
app.py CHANGED
@@ -8,59 +8,62 @@ from mixture_tiling_sdxl import StableDiffusionXLTilingPipeline
8
 
9
  MAX_SEED = np.iinfo(np.int32).max
10
  SCHEDULERS = [
11
- "LMSDiscreteScheduler",
12
- "DEISMultistepScheduler",
13
- "HeunDiscreteScheduler",
14
- "EulerAncestralDiscreteScheduler",
15
- "EulerDiscreteScheduler",
16
- "DPMSolverMultistepScheduler",
17
- "DPMSolverMultistepScheduler-Karras",
18
- "DPMSolverMultistepScheduler-Karras-SDE",
19
- "UniPCMultistepScheduler"
20
  ]
21
 
 
22
  vae = AutoencoderKL.from_pretrained(
23
  "madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16
24
  ).to("cuda")
25
 
26
- model_id="stablediffusionapi/yamermix-v8-vae"
27
  pipe = StableDiffusionXLTilingPipeline.from_pretrained(
28
  model_id,
29
  torch_dtype=torch.float16,
30
  vae=vae,
31
- use_safetensors=False, #for yammermix
32
- #variant="fp16",
33
  ).to("cuda")
34
 
35
- pipe.enable_model_cpu_offload() #<< Enable this if you have limited VRAM
36
  pipe.enable_vae_tiling()
37
  pipe.enable_vae_slicing()
38
 
39
  #region functions
40
  def select_scheduler(scheduler_name):
41
- scheduler = scheduler_name.split("-")
42
- scheduler_class_name = scheduler[0]
43
- add_kwargs = {"beta_start": 0.00085, "beta_end": 0.012, "beta_schedule": "scaled_linear", "num_train_timesteps": 1000}
44
- if len(scheduler) > 1:
 
 
 
 
 
45
  add_kwargs["use_karras_sigmas"] = True
46
- if len(scheduler) > 2:
47
  add_kwargs["algorithm_type"] = "sde-dpmsolver++"
48
  import diffusers
49
- scheduler = getattr(diffusers, scheduler_class_name)
50
- scheduler = scheduler.from_config(pipe.scheduler.config, **add_kwargs)
51
  return scheduler
52
 
53
-
54
-
55
  @spaces.GPU
56
- def predict(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs, overlap_pixels, steps, generation_seed, scheduler, tile_height, tile_width, target_height, target_width):
 
57
  global pipe
58
-
59
- # Set selected scheduler
60
  print(f"Using scheduler: {scheduler}...")
61
  pipe.scheduler = select_scheduler(scheduler)
62
-
63
- # Set seed
64
  generator = torch.Generator("cuda").manual_seed(generation_seed)
65
 
66
  target_height = int(target_height)
@@ -68,23 +71,17 @@ def predict(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs,
68
  tile_height = int(tile_height)
69
  tile_width = int(tile_width)
70
 
71
- # Mixture of Diffusers generation
72
  image = pipe(
73
- prompt=[
74
- [
75
- left_prompt,
76
- center_prompt,
77
- right_prompt,
78
- ]
79
- ],
80
  negative_prompt=negative_prompt,
81
  tile_height=tile_height,
82
  tile_width=tile_width,
83
  tile_row_overlap=0,
84
- tile_col_overlap=overlap_pixels,
85
- guidance_scale_tiles=[[left_gs, center_gs, right_gs]],
86
  height=target_height,
87
- width=target_width,
88
  generator=generator,
89
  num_inference_steps=steps,
90
  )["images"][0]
@@ -92,57 +89,53 @@ def predict(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs,
92
  return image
93
 
94
  def calc_tile_size(target_height, target_width, overlap_pixels, max_tile_width_size=1280):
95
- num_cols=3
96
- num_rows=1
97
- min_tile_dimension=8
98
- reduction_step=8
99
- max_tile_height_size=1024
100
  best_tile_width = 0
101
  best_tile_height = 0
102
  best_adjusted_target_width = 0
103
  best_adjusted_target_height = 0
104
  found_valid_solution = False
105
 
106
- # Adjust Tile Width
107
  tile_width = max_tile_width_size
108
  tile_height = max_tile_height_size
109
-
110
  while tile_width >= min_tile_dimension:
111
  horizontal_borders = num_cols - 1
112
- total_horizontal_overlap_pixels = (overlap_pixels * horizontal_borders)
113
- adjusted_target_width = tile_width * num_cols - total_horizontal_overlap_pixels
114
 
115
  vertical_borders = num_rows - 1
116
- total_vertical_overlap_pixels = (overlap_pixels * vertical_borders)
117
- adjusted_target_height = tile_height * num_rows - total_vertical_overlap_pixels
118
 
119
  if tile_width <= max_tile_width_size and adjusted_target_width <= target_width:
120
  if adjusted_target_width > best_adjusted_target_width:
121
  best_tile_width = tile_width
122
  best_adjusted_target_width = adjusted_target_width
123
  found_valid_solution = True
124
-
125
  tile_width -= reduction_step
126
 
127
- # Adjust Tile Height
128
  if found_valid_solution:
129
  tile_width = best_tile_width
130
  tile_height = max_tile_height_size
131
-
132
  while tile_height >= min_tile_dimension:
133
  horizontal_borders = num_cols - 1
134
- total_horizontal_overlap_pixels = (overlap_pixels * horizontal_borders)
135
- adjusted_target_width = tile_width * num_cols - total_horizontal_overlap_pixels
136
 
137
  vertical_borders = num_rows - 1
138
- total_vertical_overlap_pixels = (overlap_pixels * vertical_borders)
139
- adjusted_target_height = tile_height * num_rows - total_vertical_overlap_pixels
140
 
141
  if tile_height <= max_tile_height_size and adjusted_target_height <= target_height:
142
- if adjusted_target_height > best_adjusted_target_height:
143
  best_tile_height = tile_height
144
  best_adjusted_target_height = adjusted_target_height
145
-
146
  tile_height -= reduction_step
147
 
148
  new_target_height = best_adjusted_target_height
@@ -151,15 +144,12 @@ def calc_tile_size(target_height, target_width, overlap_pixels, max_tile_width_s
151
  tile_height = best_tile_height
152
 
153
  print("--- TILE SIZE CALCULATED VALUES ---")
154
- print(f"Overlap pixels (requested): {overlap_pixels}")
155
- print(f"Tile Height (divisible by 8, max {max_tile_height_size}): {tile_height}")
156
- print(f"Tile Width (divisible by 8, max {max_tile_width_size}): {tile_width}")
157
- print(f"Number of Columns (horizontal tiles): {num_cols}")
158
- print(f"Number of Rows (vertical tiles): {num_rows}")
159
- print(f"Original Target Height: {target_height}")
160
- print(f"Original Target Width: {target_width}")
161
- print(f"New Target Height (total covered height): {new_target_height}")
162
- print(f"New Target Width (total covered width): {new_target_width}\n")
163
 
164
  return new_target_height, new_target_width, tile_height, tile_width
165
 
@@ -170,207 +160,178 @@ def do_calc_tile(target_height, target_width, overlap_pixels, max_tile_size):
170
  def clear_result():
171
  return gr.update(value=None)
172
 
173
- def run_for_examples(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs, overlap_pixels, steps, generation_seed, scheduler, tile_height, tile_width, target_height, target_width, max_tile_width):
174
- return predict(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs, overlap_pixels, steps, generation_seed, scheduler, tile_height, tile_width, target_height, target_width)
 
 
175
 
176
  def randomize_seed_fn(generation_seed: int, randomize_seed: bool) -> int:
177
  if randomize_seed:
178
  generation_seed = random.randint(0, MAX_SEED)
179
  return generation_seed
 
180
 
 
181
  css = """
182
- .gradio-container .fillable {
183
- width: 95% !important;
184
- max-width: unset !important;
 
 
 
185
  }
 
 
 
 
 
 
 
 
 
 
 
186
  """
187
- title = """<h1 align="center">Mixture-of-Diffusers for SDXL Tiling Pipeline🤗</h1>
188
- <div style="display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; overflow:hidden;">
189
- <span>This <a href="https://github.com/DEVAIEXP/mixture-of-diffusers-sdxl-tiling">project</a> implements a SDXL tiling pipeline based on the original project: <a href='https://github.com/albarji/mixture-of-diffusers'>Mixture-of-Diffusers</a>. For more information, see the:
190
- <a href="https://arxiv.org/pdf/2408.06072">📜 paper </a>
191
- </div>
192
- """
193
 
 
 
194
 
195
- with gr.Blocks(css=css) as app:
196
- gr.Markdown(title)
197
  with gr.Row():
 
198
  with gr.Column(scale=7):
199
- generate_button = gr.Button("Generate")
200
  with gr.Row():
201
- with gr.Column(scale=1):
202
- gr.Markdown("### Left region")
203
- left_prompt = gr.Textbox(lines=4,
204
- label="Prompt for left side of the image")
205
- left_gs = gr.Slider(minimum=0,
206
- maximum=15,
207
- value=7,
208
- step=1,
209
- label="Left CFG scale")
210
- with gr.Column(scale=1):
211
- gr.Markdown("### Center region")
212
- center_prompt = gr.Textbox(lines=4,
213
- label="Prompt for the center of the image")
214
- center_gs = gr.Slider(minimum=0,
215
- maximum=15,
216
- value=7,
217
- step=1,
218
- label="Center CFG scale")
219
- with gr.Column(scale=1):
220
- gr.Markdown("### Right region")
221
- right_prompt = gr.Textbox(lines=4,
222
- label="Prompt for the right side of the image")
223
- right_gs = gr.Slider(minimum=0,
224
- maximum=15,
225
- value=7,
226
- step=1,
227
- label="Right CFG scale")
228
  with gr.Row():
229
- negative_prompt = gr.Textbox(lines=2,
230
- label="Negative prompt for the image",
231
- value="nsfw, lowres, bad anatomy, bad hands, duplicate, text, error, missing fingers, extra digit, fewer digits, cropped, worst quality, low quality, normal quality, jpeg artifacts, signature, watermark, blurry")
 
 
 
232
  with gr.Row():
233
- result = gr.Image(
234
- label="Generated Image",
235
- show_label=True,
236
- format="png",
237
- interactive=False,
238
- # allow_preview=True,
239
- # preview=True,
240
- scale=1,
241
 
242
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
 
244
- with gr.Sidebar(label="Parameters", open=True):
245
- gr.Markdown("### General parameters")
246
- with gr.Row():
247
- height = gr.Slider(label="Height",
248
- value=1024,
249
- step=8,
250
- visible=True,
251
- minimum=512,
252
- maximum=1024)
253
- width = gr.Slider(label="Width",
254
- value=1280,
255
- step=8,
256
- visible=True,
257
- minimum=512,
258
- maximum=3840)
259
- overlap = gr.Slider(minimum=0,
260
- maximum=512,
261
- value=128,
262
- step=8,
263
- label="Tile Overlap")
264
- max_tile_size = gr.Dropdown(label="Max. Tile Size", choices=[1024, 1280], value=1280)
265
- calc_tile = gr.Button("Calculate Tile Size")
266
- with gr.Row():
267
- tile_height = gr.Textbox(label="Tile height", value=1024, interactive=False)
268
- tile_width = gr.Textbox(label="Tile width", value=1024, interactive=False)
269
- with gr.Row():
270
- new_target_height = gr.Textbox(label="New image height", value=1024, interactive=False)
271
- new_target_width = gr.Textbox(label="New image width", value=1024, interactive=False)
272
- with gr.Row():
273
- steps = gr.Slider(minimum=1,
274
- maximum=50,
275
- value=30,
276
- step=1,
277
- label="Inference steps")
278
-
279
- generation_seed = gr.Slider(label="Seed",
280
- minimum=0,
281
- maximum=MAX_SEED,
282
- step=1,
283
- value=0)
284
- randomize_seed = gr.Checkbox(label="Randomize seed", value=False)
285
- with gr.Row():
286
- scheduler = gr.Dropdown(
287
- label="Schedulers",
288
- choices=SCHEDULERS,
289
- value=SCHEDULERS[0],
290
- )
291
  with gr.Row():
 
292
  gr.Examples(
293
  examples=[
 
294
  [
295
- "Iron Man, repulsor rays blasting enemies in destroyed cityscape, sparks, energy trails, crumbling skyscrapers, smoke, debris, cinematic lighting, photorealistic, intense action. Focus: Iron Man.",
296
- "Captain America charging forward, vibranium shield deflecting energy blasts in destroyed cityscape, collapsing buildings, rubble streets, battle-damaged suit, determined expression, distant explosions, cinematic composition, realistic rendering. Focus: Captain America.",
297
- "Thor wielding Stormbreaker in destroyed cityscape, lightning crackling, powerful strike downwards, shattered buildings, burning debris, ground trembling, Asgardian armor, cinematic photography, realistic details. Focus: Thor.",
298
- negative_prompt.value,
299
- 5, 5, 5,
300
- 160,
301
  30,
302
- 1328797844,
303
  "UniPCMultistepScheduler",
304
- 1024,
305
- 1280,
306
- 1024,
307
- 3840,
308
- 1024
309
  ],
 
310
  [
311
- "A charming house in the countryside, by jakub rozalski, sunset lighting, elegant, highly detailed, smooth, sharp focus, artstation, stunning masterpiece",
312
- "A dirt road in the countryside crossing pastures, by jakub rozalski, sunset lighting, elegant, highly detailed, smooth, sharp focus, artstation, stunning masterpiece",
313
- "An old and rusty giant robot lying on a dirt road, by jakub rozalski, dark sunset lighting, elegant, highly detailed, smooth, sharp focus, artstation, stunning masterpiece",
314
- negative_prompt.value,
315
- 7, 7, 7,
316
- 256,
317
- 30,
318
- 297984183,
319
- "DPMSolverMultistepScheduler-Karras-SDE",
320
- 1024,
321
- 1280,
322
- 1024,
323
- 3840,
324
  1280
325
  ],
 
326
  [
327
- "Abstract decorative illustration, by joan miro and gustav klimt and marlina vera and loish, elegant, intricate, highly detailed, smooth, sharp focus, vibrant colors, artstation, stunning masterpiece",
328
- "Abstract decorative illustration, by joan miro and gustav klimt and marlina vera and loish, elegant, intricate, highly detailed, smooth, sharp focus, vibrant colors, artstation, stunning masterpiece",
329
- "Abstract decorative illustration, by joan miro and gustav klimt and marlina vera and loish, elegant, intricate, highly detailed, smooth, sharp focus, vibrant colors, artstation, stunning masterpiece",
330
- negative_prompt.value,
331
- 7, 7, 7,
332
- 128,
333
- 30,
334
- 580541206,
335
- "LMSDiscreteScheduler",
336
- 1024,
337
- 768,
338
- 1024,
339
- 2048,
340
  1280
341
  ],
 
342
  [
343
- "Magical diagrams and runes written with chalk on a blackboard, elegant, intricate, highly detailed, smooth, sharp focus, artstation, stunning masterpiece",
344
- "Magical diagrams and runes written with chalk on a blackboard, elegant, intricate, highly detailed, smooth, sharp focus, artstation, stunning masterpiece",
345
- "Magical diagrams and runes written with chalk on a blackboard, elegant, intricate, highly detailed, smooth, sharp focus, artstation, stunning masterpiece",
346
- negative_prompt.value,
347
  9, 9, 9,
348
- 128,
349
- 30,
350
- 12591765619,
351
- "LMSDiscreteScheduler",
352
- 1024,
353
- 768,
354
- 1024,
355
- 2048,
356
  1280
357
  ]
358
  ],
359
- inputs=[left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs, overlap, steps, generation_seed, scheduler, tile_height, tile_width, height, width, max_tile_size],
 
 
360
  fn=run_for_examples,
361
  outputs=result,
362
  cache_examples=True
363
  )
364
-
365
- event_calc_tile_size={"fn": do_calc_tile, "inputs":[height, width, overlap, max_tile_size], "outputs":[tile_height, tile_width, new_target_height, new_target_width]}
 
 
 
 
 
366
  calc_tile.click(**event_calc_tile_size)
367
 
368
  generate_button.click(
369
  fn=clear_result,
370
  inputs=None,
371
  outputs=result,
372
- ).then(**event_calc_tile_size
373
- ).then(
374
  fn=randomize_seed_fn,
375
  inputs=[generation_seed, randomize_seed],
376
  outputs=generation_seed,
@@ -378,7 +339,9 @@ with gr.Blocks(css=css) as app:
378
  api_name=False,
379
  ).then(
380
  fn=predict,
381
- inputs=[left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs, overlap, steps, generation_seed, scheduler, tile_height, tile_width, new_target_height, new_target_width],
 
 
382
  outputs=result,
383
  )
384
 
 
8
 
9
  MAX_SEED = np.iinfo(np.int32).max
10
  SCHEDULERS = [
11
+ "LMSDiscreteScheduler",
12
+ "DEISMultistepScheduler",
13
+ "HeunDiscreteScheduler",
14
+ "EulerAncestralDiscreteScheduler",
15
+ "EulerDiscreteScheduler",
16
+ "DPMSolverMultistepScheduler",
17
+ "DPMSolverMultistepScheduler-Karras",
18
+ "DPMSolverMultistepScheduler-Karras-SDE",
19
+ "UniPCMultistepScheduler"
20
  ]
21
 
22
+ # 로딩: VAE 및 타일링 파이프라인 모델 초기화
23
  vae = AutoencoderKL.from_pretrained(
24
  "madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16
25
  ).to("cuda")
26
 
27
+ model_id = "stablediffusionapi/yamermix-v8-vae"
28
  pipe = StableDiffusionXLTilingPipeline.from_pretrained(
29
  model_id,
30
  torch_dtype=torch.float16,
31
  vae=vae,
32
+ use_safetensors=False, # for yammermix
 
33
  ).to("cuda")
34
 
35
+ pipe.enable_model_cpu_offload() # VRAM이 제한된 경우 사용
36
  pipe.enable_vae_tiling()
37
  pipe.enable_vae_slicing()
38
 
39
  #region functions
40
  def select_scheduler(scheduler_name):
41
+ scheduler_parts = scheduler_name.split("-")
42
+ scheduler_class_name = scheduler_parts[0]
43
+ add_kwargs = {
44
+ "beta_start": 0.00085,
45
+ "beta_end": 0.012,
46
+ "beta_schedule": "scaled_linear",
47
+ "num_train_timesteps": 1000
48
+ }
49
+ if len(scheduler_parts) > 1:
50
  add_kwargs["use_karras_sigmas"] = True
51
+ if len(scheduler_parts) > 2:
52
  add_kwargs["algorithm_type"] = "sde-dpmsolver++"
53
  import diffusers
54
+ scheduler_cls = getattr(diffusers, scheduler_class_name)
55
+ scheduler = scheduler_cls.from_config(pipe.scheduler.config, **add_kwargs)
56
  return scheduler
57
 
 
 
58
  @spaces.GPU
59
+ def predict(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs,
60
+ overlap_pixels, steps, generation_seed, scheduler, tile_height, tile_width, target_height, target_width):
61
  global pipe
62
+ # 스케줄러 선택
 
63
  print(f"Using scheduler: {scheduler}...")
64
  pipe.scheduler = select_scheduler(scheduler)
65
+
66
+ # 시드 설정
67
  generator = torch.Generator("cuda").manual_seed(generation_seed)
68
 
69
  target_height = int(target_height)
 
71
  tile_height = int(tile_height)
72
  tile_width = int(tile_width)
73
 
74
+ # 타일링된 이미지 생성 (좌/중앙/우 영역)
75
  image = pipe(
76
+ prompt=[[left_prompt, center_prompt, right_prompt]],
 
 
 
 
 
 
77
  negative_prompt=negative_prompt,
78
  tile_height=tile_height,
79
  tile_width=tile_width,
80
  tile_row_overlap=0,
81
+ tile_col_overlap=overlap_pixels,
82
+ guidance_scale_tiles=[[left_gs, center_gs, right_gs]],
83
  height=target_height,
84
+ width=target_width,
85
  generator=generator,
86
  num_inference_steps=steps,
87
  )["images"][0]
 
89
  return image
90
 
91
  def calc_tile_size(target_height, target_width, overlap_pixels, max_tile_width_size=1280):
92
+ num_cols = 3
93
+ num_rows = 1
94
+ min_tile_dimension = 8
95
+ reduction_step = 8
96
+ max_tile_height_size = 1024
97
  best_tile_width = 0
98
  best_tile_height = 0
99
  best_adjusted_target_width = 0
100
  best_adjusted_target_height = 0
101
  found_valid_solution = False
102
 
103
+ # 타일 너비 결정
104
  tile_width = max_tile_width_size
105
  tile_height = max_tile_height_size
 
106
  while tile_width >= min_tile_dimension:
107
  horizontal_borders = num_cols - 1
108
+ total_horizontal_overlap = overlap_pixels * horizontal_borders
109
+ adjusted_target_width = tile_width * num_cols - total_horizontal_overlap
110
 
111
  vertical_borders = num_rows - 1
112
+ total_vertical_overlap = overlap_pixels * vertical_borders
113
+ adjusted_target_height = tile_height * num_rows - total_vertical_overlap
114
 
115
  if tile_width <= max_tile_width_size and adjusted_target_width <= target_width:
116
  if adjusted_target_width > best_adjusted_target_width:
117
  best_tile_width = tile_width
118
  best_adjusted_target_width = adjusted_target_width
119
  found_valid_solution = True
 
120
  tile_width -= reduction_step
121
 
122
+ # 타일 높이 결정
123
  if found_valid_solution:
124
  tile_width = best_tile_width
125
  tile_height = max_tile_height_size
 
126
  while tile_height >= min_tile_dimension:
127
  horizontal_borders = num_cols - 1
128
+ total_horizontal_overlap = overlap_pixels * horizontal_borders
129
+ adjusted_target_width = tile_width * num_cols - total_horizontal_overlap
130
 
131
  vertical_borders = num_rows - 1
132
+ total_vertical_overlap = overlap_pixels * vertical_borders
133
+ adjusted_target_height = tile_height * num_rows - total_vertical_overlap
134
 
135
  if tile_height <= max_tile_height_size and adjusted_target_height <= target_height:
136
+ if adjusted_target_height > best_adjusted_target_height:
137
  best_tile_height = tile_height
138
  best_adjusted_target_height = adjusted_target_height
 
139
  tile_height -= reduction_step
140
 
141
  new_target_height = best_adjusted_target_height
 
144
  tile_height = best_tile_height
145
 
146
  print("--- TILE SIZE CALCULATED VALUES ---")
147
+ print(f"Requested Overlap Pixels: {overlap_pixels}")
148
+ print(f"Tile Height (max {max_tile_height_size}, divisible by 8): {tile_height}")
149
+ print(f"Tile Width (max {max_tile_width_size}, divisible by 8): {tile_width}")
150
+ print(f"Columns: {num_cols} | Rows: {num_rows}")
151
+ print(f"Original Target: {target_height} x {target_width}")
152
+ print(f"Adjusted Target: {new_target_height} x {new_target_width}\n")
 
 
 
153
 
154
  return new_target_height, new_target_width, tile_height, tile_width
155
 
 
160
  def clear_result():
161
  return gr.update(value=None)
162
 
163
+ def run_for_examples(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs,
164
+ overlap_pixels, steps, generation_seed, scheduler, tile_height, tile_width, target_height, target_width, max_tile_width):
165
+ return predict(left_prompt, center_prompt, right_prompt, negative_prompt, left_gs, center_gs, right_gs,
166
+ overlap_pixels, steps, generation_seed, scheduler, tile_height, tile_width, target_height, target_width)
167
 
168
  def randomize_seed_fn(generation_seed: int, randomize_seed: bool) -> int:
169
  if randomize_seed:
170
  generation_seed = random.randint(0, MAX_SEED)
171
  return generation_seed
172
+ #endregion
173
 
174
+ # 개선된 CSS: 배경색, 여백, 그림자 등을 추가하여 UI를 깔끔하게 표현
175
  css = """
176
+ body { background-color: #f0f2f5; }
177
+ .gradio-container {
178
+ background: #ffffff;
179
+ border-radius: 15px;
180
+ padding: 20px;
181
+ box-shadow: 0 4px 10px rgba(0,0,0,0.1);
182
  }
183
+ .gradio-container h1 { color: #333333; }
184
+ .fillable { width: 95% !important; max-width: unset !important; }
185
+ """
186
+
187
+ # 제목 및 간단한 설명
188
+ title = """
189
+ <h1 align="center" style="margin-bottom: 0.2em;">Mixture-of-Diffusers for SDXL Tiling Pipeline 🤗</h1>
190
+ <p align="center" style="font-size:1.1em; color:#555;">
191
+ 좌/중앙/우 세 영역 각각에 다른 프롬프트를 적용하여 타일링 이미지를 생성합니다.<br>
192
+ 아래의 예제나 직접 프롬프트를 입력하여 창의적인 이미지를 만들어보세요.
193
+ </p>
194
  """
 
 
 
 
 
 
195
 
196
+ with gr.Blocks(css=css, title="SDXL Tiling Pipeline") as app:
197
+ gr.Markdown(title)
198
 
 
 
199
  with gr.Row():
200
+ # 좌/중앙/우 영역 프롬프트 및 결과 출력 영역
201
  with gr.Column(scale=7):
202
+ generate_button = gr.Button("Generate", elem_id="generate_btn")
203
  with gr.Row():
204
+ with gr.Column(variant="panel"):
205
+ gr.Markdown("### Left Region")
206
+ left_prompt = gr.Textbox(lines=4, placeholder="예: 울창한 숲과 햇살이 비추는 나무...", label="Left Prompt")
207
+ left_gs = gr.Slider(minimum=0, maximum=15, value=7, step=1, label="Left CFG Scale")
208
+ with gr.Column(variant="panel"):
209
+ gr.Markdown("### Center Region")
210
+ center_prompt = gr.Textbox(lines=4, placeholder="예: 잔잔한 호수와 반짝이는 수면...", label="Center Prompt")
211
+ center_gs = gr.Slider(minimum=0, maximum=15, value=7, step=1, label="Center CFG Scale")
212
+ with gr.Column(variant="panel"):
213
+ gr.Markdown("### Right Region")
214
+ right_prompt = gr.Textbox(lines=4, placeholder="예: 웅장한 산맥과 하늘을 가르는 구름...", label="Right Prompt")
215
+ right_gs = gr.Slider(minimum=0, maximum=15, value=7, step=1, label="Right CFG Scale")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
  with gr.Row():
217
+ negative_prompt = gr.Textbox(
218
+ lines=2,
219
+ label="Negative Prompt",
220
+ placeholder="예: blurry, low resolution, artifacts, poor details",
221
+ value="blurry, low resolution, artifacts, poor details"
222
+ )
223
  with gr.Row():
224
+ result = gr.Image(label="Generated Image", show_label=True, format="png", interactive=False, scale=1)
 
 
 
 
 
 
 
225
 
226
+ # 우측 사이드바: 파라미터 및 타일 크기 계산
227
+ with gr.Sidebar(label="Parameters", open=True):
228
+ gr.Markdown("### Generation Parameters")
229
+ with gr.Row():
230
+ height = gr.Slider(label="Target Height", value=1024, step=8, minimum=512, maximum=1024)
231
+ width = gr.Slider(label="Target Width", value=1280, step=8, minimum=512, maximum=3840)
232
+ overlap = gr.Slider(minimum=0, maximum=512, value=128, step=8, label="Tile Overlap")
233
+ max_tile_size = gr.Dropdown(label="Max Tile Size", choices=[1024, 1280], value=1280)
234
+ calc_tile = gr.Button("Calculate Tile Size")
235
+ with gr.Row():
236
+ tile_height = gr.Textbox(label="Tile Height", value=1024, interactive=False)
237
+ tile_width = gr.Textbox(label="Tile Width", value=1024, interactive=False)
238
+ with gr.Row():
239
+ new_target_height = gr.Textbox(label="New Image Height", value=1024, interactive=False)
240
+ new_target_width = gr.Textbox(label="New Image Width", value=1280, interactive=False)
241
+ with gr.Row():
242
+ steps = gr.Slider(minimum=1, maximum=50, value=30, step=1, label="Inference Steps")
243
+ generation_seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
244
+ randomize_seed = gr.Checkbox(label="Randomize Seed", value=False)
245
+ with gr.Row():
246
+ scheduler = gr.Dropdown(label="Scheduler", choices=SCHEDULERS, value=SCHEDULERS[0])
247
 
248
+ # 예제 탭: 목적에 맞는 예시 프롬프트 제공
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
  with gr.Row():
250
+ gr.Markdown("### Example Prompts")
251
  gr.Examples(
252
  examples=[
253
+ # Example 1: Serene Nature
254
  [
255
+ "Lush green forest with sun rays filtering through the canopy",
256
+ "Crystal clear lake reflecting a vibrant sky",
257
+ "Majestic mountains with snowy peaks in the distance",
258
+ "blurry, low resolution, artifacts, poor details",
259
+ 7, 7, 7,
260
+ 128,
261
  30,
262
+ 123456789,
263
  "UniPCMultistepScheduler",
264
+ 1024, 1280,
265
+ 1024, 1920,
266
+ 1280
 
 
267
  ],
268
+ # Example 2: Futuristic Cityscape
269
  [
270
+ "Vibrant city street with neon signs and bustling crowds",
271
+ "Sleek modern skyscrapers with digital billboards",
272
+ "High-speed maglev train gliding over a futuristic urban landscape",
273
+ "blurry, poorly rendered, low quality, disfigured",
274
+ 8, 8, 8,
275
+ 100,
276
+ 35,
277
+ 987654321,
278
+ "EulerDiscreteScheduler",
279
+ 1024, 1280,
280
+ 1024, 1920,
 
 
281
  1280
282
  ],
283
+ # Example 3: Abstract Art
284
  [
285
+ "Vibrant abstract strokes with fluid, swirling patterns in cool tones",
286
+ "Interlocking geometric shapes bursting with color and texture",
287
+ "Dynamic composition of splattered ink with smooth gradients",
288
+ "text, watermark, signature, distorted",
289
+ 6, 6, 6,
290
+ 80,
291
+ 25,
292
+ 192837465,
293
+ "DPMSolverMultistepScheduler-Karras",
294
+ 1024, 1280,
295
+ 1024, 1920,
 
 
296
  1280
297
  ],
298
+ # Example 4: Fantasy Landscape
299
  [
300
+ "Enchanted forest with glowing bioluminescent plants and mystical fog",
301
+ "Ancient castle with towering spires bathed in moonlight",
302
+ "Majestic dragon soaring above a starry night sky",
303
+ "low quality, artifact, deformed, sketchy",
304
  9, 9, 9,
305
+ 150,
306
+ 40,
307
+ 1029384756,
308
+ "DPMSolverMultistepScheduler-Karras-SDE",
309
+ 1024, 1280,
310
+ 1024, 1920,
 
 
311
  1280
312
  ]
313
  ],
314
+ inputs=[left_prompt, center_prompt, right_prompt, negative_prompt,
315
+ left_gs, center_gs, right_gs, overlap, steps, generation_seed,
316
+ scheduler, tile_height, tile_width, height, width, max_tile_size],
317
  fn=run_for_examples,
318
  outputs=result,
319
  cache_examples=True
320
  )
321
+
322
+ # 이벤트 연결: 타일 사이즈 계산 이미지 생성
323
+ event_calc_tile_size = {
324
+ "fn": do_calc_tile,
325
+ "inputs": [height, width, overlap, max_tile_size],
326
+ "outputs": [tile_height, tile_width, new_target_height, new_target_width]
327
+ }
328
  calc_tile.click(**event_calc_tile_size)
329
 
330
  generate_button.click(
331
  fn=clear_result,
332
  inputs=None,
333
  outputs=result,
334
+ ).then(**event_calc_tile_size).then(
 
335
  fn=randomize_seed_fn,
336
  inputs=[generation_seed, randomize_seed],
337
  outputs=generation_seed,
 
339
  api_name=False,
340
  ).then(
341
  fn=predict,
342
+ inputs=[left_prompt, center_prompt, right_prompt, negative_prompt,
343
+ left_gs, center_gs, right_gs, overlap, steps, generation_seed,
344
+ scheduler, tile_height, tile_width, new_target_height, new_target_width],
345
  outputs=result,
346
  )
347