File size: 14,685 Bytes
c4b1a2f
 
 
 
 
 
 
 
 
 
6891a4e
 
 
 
 
 
 
 
 
c4b1a2f
 
78ba3f1
c4b1a2f
 
 
 
6891a4e
c4b1a2f
 
 
 
6891a4e
c4b1a2f
 
6891a4e
c4b1a2f
 
 
 
 
6891a4e
 
 
 
 
 
 
 
 
c4b1a2f
6891a4e
c4b1a2f
 
6891a4e
 
c4b1a2f
 
ab97210
6891a4e
 
c4b1a2f
 
 
 
 
 
 
 
 
 
 
6891a4e
c4b1a2f
 
 
 
6891a4e
 
c4b1a2f
6891a4e
c4b1a2f
 
 
 
 
 
6891a4e
 
 
 
 
c4b1a2f
 
 
 
 
 
 
 
 
 
6891a4e
 
c4b1a2f
 
6891a4e
 
c4b1a2f
 
 
 
 
 
 
 
 
 
 
 
 
6891a4e
 
c4b1a2f
 
6891a4e
 
c4b1a2f
 
6891a4e
c4b1a2f
 
 
 
 
 
 
 
 
 
6891a4e
 
 
 
 
 
c4b1a2f
 
 
 
 
 
 
 
 
 
 
 
 
 
6891a4e
c4b1a2f
d8fc7c0
c4b1a2f
6891a4e
 
 
 
 
 
c4b1a2f
6891a4e
 
78ba3f1
 
 
 
 
 
 
6891a4e
 
 
 
 
78ba3f1
 
6891a4e
c4b1a2f
5764403
6891a4e
 
c4b1a2f
 
d8fc7c0
c4b1a2f
6891a4e
c4b1a2f
6891a4e
 
 
 
 
 
 
 
 
 
 
 
c4b1a2f
6891a4e
 
 
 
 
 
c4b1a2f
6891a4e
c4b1a2f
d8fc7c0
6891a4e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c9ce198
78ba3f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c4b1a2f
a594406
 
 
 
d8fc7c0
78ba3f1
6891a4e
 
 
 
 
 
 
c4b1a2f
 
 
 
 
 
6891a4e
c4b1a2f
 
 
 
 
 
 
6891a4e
 
 
c4b1a2f
 
49963bb
c4b1a2f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
import random
import gradio as gr
import numpy as np
import spaces
import torch
from diffusers import AutoencoderKL
from mixture_tiling_sdxl import StableDiffusionXLTilingPipeline

MAX_SEED = np.iinfo(np.int32).max
SCHEDULERS = [
    "LMSDiscreteScheduler",
    "DEISMultistepScheduler",
    "HeunDiscreteScheduler",
    "EulerAncestralDiscreteScheduler",
    "EulerDiscreteScheduler",
    "DPMSolverMultistepScheduler",
    "DPMSolverMultistepScheduler-Karras",
    "DPMSolverMultistepScheduler-Karras-SDE",
    "UniPCMultistepScheduler"
]

# ๋ชจ๋ธ ๋กœ๋”ฉ: VAE ๋ฐ ํƒ€์ผ๋ง ํŒŒ์ดํ”„๋ผ์ธ ์ดˆ๊ธฐํ™”
vae = AutoencoderKL.from_pretrained(
    "madebyollin/sdxl-vae-fp16-fix", torch_dtype=torch.float16
).to("cuda")

model_id = "stablediffusionapi/yamermix-v8-vae"
pipe = StableDiffusionXLTilingPipeline.from_pretrained(
    model_id,
    torch_dtype=torch.float16,
    vae=vae,
    use_safetensors=False,  # for yammermix
).to("cuda")

pipe.enable_model_cpu_offload()  # VRAM์ด ์ œํ•œ๋œ ๊ฒฝ์šฐ ์‚ฌ์šฉ
pipe.enable_vae_tiling()
pipe.enable_vae_slicing()

#region functions
def select_scheduler(scheduler_name):
    scheduler_parts = scheduler_name.split("-")
    scheduler_class_name = scheduler_parts[0]
    add_kwargs = {
        "beta_start": 0.00085,
        "beta_end": 0.012,
        "beta_schedule": "scaled_linear",
        "num_train_timesteps": 1000
    }
    if len(scheduler_parts) > 1:
        add_kwargs["use_karras_sigmas"] = True
    if len(scheduler_parts) > 2:
        add_kwargs["algorithm_type"] = "sde-dpmsolver++"
    import diffusers
    scheduler_cls = getattr(diffusers, scheduler_class_name)
    scheduler = scheduler_cls.from_config(pipe.scheduler.config, **add_kwargs)
    return scheduler

@spaces.GPU
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):
    global pipe
    print(f"Using scheduler: {scheduler}...")
    pipe.scheduler = select_scheduler(scheduler)
    generator = torch.Generator("cuda").manual_seed(generation_seed)
    
    target_height = int(target_height)
    target_width = int(target_width)
    tile_height = int(tile_height)
    tile_width = int(tile_width)
    
    image = pipe(
        prompt=[[left_prompt, center_prompt, right_prompt]],
        negative_prompt=negative_prompt,
        tile_height=tile_height,
        tile_width=tile_width,
        tile_row_overlap=0,
        tile_col_overlap=overlap_pixels,
        guidance_scale_tiles=[[left_gs, center_gs, right_gs]],
        height=target_height,
        width=target_width,
        generator=generator,
        num_inference_steps=steps,
    )["images"][0]
    return image

def calc_tile_size(target_height, target_width, overlap_pixels, max_tile_width_size=1280):
    num_cols = 3
    num_rows = 1    
    min_tile_dimension = 8
    reduction_step = 8
    max_tile_height_size = 1024
    best_tile_width = 0
    best_tile_height = 0
    best_adjusted_target_width = 0
    best_adjusted_target_height = 0
    found_valid_solution = False

    tile_width = max_tile_width_size
    tile_height = max_tile_height_size
    while tile_width >= min_tile_dimension:
        horizontal_borders = num_cols - 1
        total_horizontal_overlap = overlap_pixels * horizontal_borders
        adjusted_target_width = tile_width * num_cols - total_horizontal_overlap

        vertical_borders = num_rows - 1
        total_vertical_overlap = overlap_pixels * vertical_borders
        adjusted_target_height = tile_height * num_rows - total_vertical_overlap

        if tile_width <= max_tile_width_size and adjusted_target_width <= target_width:
            if adjusted_target_width > best_adjusted_target_width:
                best_tile_width = tile_width
                best_adjusted_target_width = adjusted_target_width
                found_valid_solution = True
        tile_width -= reduction_step

    if found_valid_solution:
        tile_width = best_tile_width
        tile_height = max_tile_height_size
        while tile_height >= min_tile_dimension:
            horizontal_borders = num_cols - 1
            total_horizontal_overlap = overlap_pixels * horizontal_borders
            adjusted_target_width = tile_width * num_cols - total_horizontal_overlap

            vertical_borders = num_rows - 1
            total_vertical_overlap = overlap_pixels * vertical_borders
            adjusted_target_height = tile_height * num_rows - total_vertical_overlap
        
            if tile_height <= max_tile_height_size and adjusted_target_height <= target_height:
                if adjusted_target_height > best_adjusted_target_height:
                    best_tile_height = tile_height
                    best_adjusted_target_height = adjusted_target_height
            tile_height -= reduction_step

    new_target_height = best_adjusted_target_height
    new_target_width = best_adjusted_target_width
    tile_width = best_tile_width
    tile_height = best_tile_height

    print("--- TILE SIZE CALCULATED VALUES ---")    
    print(f"Requested Overlap Pixels: {overlap_pixels}")
    print(f"Tile Height (max {max_tile_height_size}, divisible by 8): {tile_height}")
    print(f"Tile Width (max {max_tile_width_size}, divisible by 8): {tile_width}")
    print(f"Columns: {num_cols} | Rows: {num_rows}")
    print(f"Original Target: {target_height} x {target_width}")
    print(f"Adjusted Target: {new_target_height} x {new_target_width}\n")

    return new_target_height, new_target_width, tile_height, tile_width

def do_calc_tile(target_height, target_width, overlap_pixels, max_tile_size):    
    new_target_height, new_target_width, tile_height, tile_width = calc_tile_size(target_height, target_width, overlap_pixels, max_tile_size)    
    return gr.update(value=tile_height), gr.update(value=tile_width), gr.update(value=new_target_height), gr.update(value=new_target_width)

def clear_result():
    return gr.update(value=None)

def randomize_seed_fn(generation_seed: int, randomize_seed: bool) -> int:
    if randomize_seed:
        generation_seed = random.randint(0, MAX_SEED)
    return generation_seed
#endregion

# CSS ๊ฐœ์„ : ๋ฐฐ๊ฒฝ, ์—ฌ๋ฐฑ, ๊ทธ๋ฆผ์ž ๋ฐ ์˜ˆ์ œ ์˜์—ญ ์ค‘์•™ ๋ฐฐ์น˜
css = """
body { background-color: #f0f2f5; }
.gradio-container {
    background: #ffffff;
    border-radius: 15px;
    padding: 20px;
    box-shadow: 0 4px 10px rgba(0,0,0,0.1);
}
.gradio-container h1 { color: #333333; }
.fillable { width: 95% !important; max-width: unset !important; }
#examples_container {
    margin: auto;
    width: 90%;
}
#examples_row {
    justify-content: center;
}
"""

title = """
<h1 align="center" style="margin-bottom: 0.2em;">Mixture-of-Diffusers for SDXL Tiling Pipeline ๐Ÿค—</h1>
<p align="center" style="font-size:1.1em; color:#555;">
    ์ขŒ/์ค‘์•™/์šฐ ๊ฐ ์˜์—ญ์— ๋‹ค๋ฅธ ํ”„๋กฌํ”„ํŠธ๋ฅผ ์ ์šฉํ•˜์—ฌ ํƒ€์ผ๋ง ์ด๋ฏธ์ง€๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.<br>
    ์•„๋ž˜ ์˜ˆ์ œ๋ฅผ ํด๋ฆญํ•˜๋ฉด ์ž…๋ ฅ์ฐฝ์— ๊ฐ’์ด ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.
</p>
"""

with gr.Blocks(css=css, title="SDXL Tiling Pipeline") as app:
    gr.Markdown(title)

    with gr.Row():
        # ์ขŒ/์ค‘์•™/์šฐ ํ”„๋กฌํ”„ํŠธ ๋ฐ ๊ฒฐ๊ณผ ์˜์—ญ
        with gr.Column(scale=7):
            generate_button = gr.Button("Generate", elem_id="generate_btn")
            with gr.Row():
                with gr.Column(variant="panel"):
                    gr.Markdown("### Left Region")
                    left_prompt = gr.Textbox(lines=4, placeholder="์˜ˆ: ์šธ์ฐฝํ•œ ์ˆฒ๊ณผ ํ–‡์‚ด์ด ๋น„์ถ”๋Š” ๋‚˜๋ฌด...", label="Left Prompt")
                    left_gs = gr.Slider(minimum=0, maximum=15, value=7, step=1, label="Left CFG Scale")
                with gr.Column(variant="panel"):
                    gr.Markdown("### Center Region")
                    center_prompt = gr.Textbox(lines=4, placeholder="์˜ˆ: ์ž”์ž”ํ•œ ํ˜ธ์ˆ˜์™€ ๋ฐ˜์ง์ด๋Š” ์ˆ˜๋ฉด...", label="Center Prompt")
                    center_gs = gr.Slider(minimum=0, maximum=15, value=7, step=1, label="Center CFG Scale")
                with gr.Column(variant="panel"):
                    gr.Markdown("### Right Region")
                    right_prompt = gr.Textbox(lines=4, placeholder="์˜ˆ: ์›…์žฅํ•œ ์‚ฐ๋งฅ๊ณผ ํ•˜๋Š˜์„ ๊ฐ€๋ฅด๋Š” ๊ตฌ๋ฆ„...", label="Right Prompt")
                    right_gs = gr.Slider(minimum=0, maximum=15, value=7, step=1, label="Right CFG Scale")
            with gr.Row():
                negative_prompt = gr.Textbox(
                    lines=2,
                    label="Negative Prompt",
                    placeholder="์˜ˆ: blurry, low resolution, artifacts, poor details",
                    value="blurry, low resolution, artifacts, poor details"
                )
            with gr.Row():
                result = gr.Image(label="Generated Image", show_label=True, format="png", interactive=False, scale=1)

        # ์‚ฌ์ด๋“œ๋ฐ”: ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฐ ํƒ€์ผ ํฌ๊ธฐ ๊ณ„์‚ฐ
        with gr.Sidebar(label="Parameters", open=True):
            gr.Markdown("### Generation Parameters")
            with gr.Row():
                height = gr.Slider(label="Target Height", value=1024, step=8, minimum=512, maximum=1024)
                width = gr.Slider(label="Target Width", value=1280, step=8, minimum=512, maximum=3840)
                overlap = gr.Slider(minimum=0, maximum=512, value=128, step=8, label="Tile Overlap")
                max_tile_size = gr.Dropdown(label="Max Tile Size", choices=[1024, 1280], value=1280)
                calc_tile = gr.Button("Calculate Tile Size")
            with gr.Row():
                tile_height = gr.Textbox(label="Tile Height", value=1024, interactive=False)
                tile_width = gr.Textbox(label="Tile Width", value=1024, interactive=False)
            with gr.Row():
                new_target_height = gr.Textbox(label="New Image Height", value=1024, interactive=False)
                new_target_width = gr.Textbox(label="New Image Width", value=1280, interactive=False)
            with gr.Row():
                steps = gr.Slider(minimum=1, maximum=50, value=30, step=1, label="Inference Steps")
                generation_seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
                randomize_seed = gr.Checkbox(label="Randomize Seed", value=False)
            with gr.Row():
                scheduler = gr.Dropdown(label="Scheduler", choices=SCHEDULERS, value=SCHEDULERS[0])

    # ์ค‘์•™์— ๋ฐฐ์น˜๋œ ์˜ˆ์ œ ์˜์—ญ
    with gr.Row(elem_id="examples_row"):
        with gr.Column(scale=12, elem_id="examples_container"):
            gr.Markdown("### Example Prompts")
            gr.Examples(
                examples=[
                    [
                        "Lush green forest with sun rays filtering through the canopy",
                        "Crystal clear lake reflecting a vibrant sky",
                        "Majestic mountains with snowy peaks in the distance",
                        "blurry, low resolution, artifacts, poor details",
                        7, 7, 7,
                        128,
                        30,
                        123456789,
                        "UniPCMultistepScheduler",
                        1024, 1280,
                        1024, 1920,
                        1280
                    ],
                    [
                        "Vibrant city street with neon signs and bustling crowds",
                        "Sleek modern skyscrapers with digital billboards",
                        "High-speed maglev train gliding over a futuristic urban landscape",
                        "blurry, poorly rendered, low quality, disfigured",
                        8, 8, 8,
                        100,
                        35,
                        987654321,
                        "EulerDiscreteScheduler",
                        1024, 1280,
                        1024, 1920,
                        1280
                    ],
                    [
                        "Vibrant abstract strokes with fluid, swirling patterns in cool tones",
                        "Interlocking geometric shapes bursting with color and texture",
                        "Dynamic composition of splattered ink with smooth gradients",
                        "text, watermark, signature, distorted",
                        6, 6, 6,
                        80,
                        25,
                        192837465,
                        "DPMSolverMultistepScheduler-Karras",
                        1024, 1280,
                        1024, 1920,
                        1280
                    ],
                    [
                        "Enchanted forest with glowing bioluminescent plants and mystical fog",
                        "Ancient castle with towering spires bathed in moonlight",
                        "Majestic dragon soaring above a starry night sky",
                        "low quality, artifact, deformed, sketchy",
                        9, 9, 9,
                        150,
                        40,
                        1029384756,
                        "DPMSolverMultistepScheduler-Karras-SDE",
                        1024, 1280,
                        1024, 1920,
                        1280
                    ]
                ],
                # ์˜ˆ์ œ ํด๋ฆญ ์‹œ ๊ฐ ์ž…๋ ฅ์ฐฝ์— ๊ฐ’์ด ์ฑ„์›Œ์ง€๋„๋ก "inputs" ์ธ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
                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],
                cache_examples=False
            )

    # ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ: ํƒ€์ผ ์‚ฌ์ด์ฆˆ ๊ณ„์‚ฐ ๋ฐ ์ด๋ฏธ์ง€ ์ƒ์„ฑ
    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]
    }
    calc_tile.click(**event_calc_tile_size)
    
    generate_button.click(
        fn=clear_result,
        inputs=None,
        outputs=result,
    ).then(**event_calc_tile_size).then(
        fn=randomize_seed_fn,
        inputs=[generation_seed, randomize_seed],
        outputs=generation_seed,
        queue=False,
        api_name=False,
    ).then(
        fn=predict,
        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],
        outputs=result,
    )

app.launch(share=False)