naykun commited on
Commit
bf5bf84
·
verified ·
1 Parent(s): 648705d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +225 -0
app.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from diffusers import QwenImageLayeredPipeline
2
+ import torch
3
+ from PIL import Image
4
+ from pptx import Presentation
5
+ import os
6
+ import gradio as gr
7
+ import uuid
8
+ import numpy as np
9
+ import random
10
+ import spaces
11
+ import tempfile
12
+
13
+
14
+ LOG_DIR = "/tmp/local"
15
+ MAX_SEED = np.iinfo(np.int32).max
16
+
17
+ pipeline = QwenImageLayeredPipeline.from_pretrained("Qwen/Qwen-Image-Layered")
18
+ pipeline = pipeline.to("cuda", torch.bfloat16)
19
+ pipeline.set_progress_bar_config(disable=None)
20
+
21
+ def ensure_dirname(path: str):
22
+ if path and not os.path.exists(path):
23
+ os.makedirs(path, exist_ok=True)
24
+
25
+ def random_str(length=8):
26
+ return uuid.uuid4().hex[:length]
27
+
28
+ def imagelist_to_pptx(img_files):
29
+ with Image.open(img_files[0]) as img:
30
+ img_width_px, img_height_px = img.size
31
+
32
+ def px_to_emu(px, dpi=96):
33
+ inch = px / dpi
34
+ emu = inch * 914400
35
+ return int(emu)
36
+
37
+ prs = Presentation()
38
+ prs.slide_width = px_to_emu(img_width_px)
39
+ prs.slide_height = px_to_emu(img_height_px)
40
+
41
+ slide = prs.slides.add_slide(prs.slide_layouts[6])
42
+
43
+ left = top = 0
44
+ for img_path in img_files:
45
+ slide.shapes.add_picture(img_path, left, top, width=px_to_emu(img_width_px), height=px_to_emu(img_height_px))
46
+
47
+ with tempfile.NamedTemporaryFile(suffix=".pptx", delete=False) as tmp:
48
+ prs.save(tmp.name)
49
+ return tmp.name
50
+
51
+ def export_gallery(images):
52
+ # images: list of image file paths
53
+ images = [e[0] for e in images]
54
+ pptx_path = imagelist_to_pptx(images)
55
+ return pptx_path
56
+
57
+ @spaces.GPU(duration=300)
58
+ def infer(input_image,
59
+ seed=777,
60
+ randomize_seed=False,
61
+ prompt=None,
62
+ neg_prompt=" ",
63
+ true_guidance_scale=4.0,
64
+ num_inference_steps=50,
65
+ layer=4,
66
+ cfg_norm=True,
67
+ use_en_prompt=True):
68
+
69
+ if randomize_seed:
70
+ seed = random.randint(0, MAX_SEED)
71
+
72
+ if isinstance(input_image, list):
73
+ input_image = input_image[0]
74
+
75
+ if isinstance(input_image, str):
76
+ pil_image = Image.open(input_image).convert("RGB").convert("RGBA")
77
+ elif isinstance(input_image, Image.Image):
78
+ pil_image = input_image.convert("RGB").convert("RGBA")
79
+ elif isinstance(input_image, np.ndarray):
80
+ pil_image = Image.fromarray(input_image).convert("RGB").convert("RGBA")
81
+ else:
82
+ raise ValueError("Unsupported input_image type: %s" % type(input_image))
83
+
84
+ inputs = {
85
+ "image": pil_image,
86
+ "generator": torch.Generator(device='cuda').manual_seed(seed),
87
+ "true_cfg_scale": true_guidance_scale,
88
+ "prompt": prompt,
89
+ "negative_prompt": neg_prompt,
90
+ "num_inference_steps": num_inference_steps,
91
+ "num_images_per_prompt": 1,
92
+ "layers": layer,
93
+ "resolution": 640, # Using different bucket (640, 1024) to determine the resolution. For this version, 640 is recommended
94
+ "cfg_normalize": cfg_norm, # Whether enable cfg normalization.
95
+ "use_en_prompt": use_en_prompt,
96
+ }
97
+ print(inputs)
98
+ with torch.inference_mode():
99
+ output = pipeline(**inputs)
100
+ output_images = output.images[0]
101
+
102
+ output = []
103
+ for i, image in enumerate(output_images):
104
+ output.append(image)
105
+ return output
106
+
107
+ ensure_dirname(LOG_DIR)
108
+ examples = [
109
+ "assets/test_images/1.png",
110
+ "assets/test_images/2.png",
111
+ "assets/test_images/3.png",
112
+ "assets/test_images/4.png",
113
+ "assets/test_images/5.png",
114
+ "assets/test_images/6.png",
115
+ "assets/test_images/7.png",
116
+ "assets/test_images/8.png",
117
+ "assets/test_images/9.png",
118
+ "assets/test_images/10.png",
119
+ "assets/test_images/11.png",
120
+ "assets/test_images/12.png",
121
+ "assets/test_images/13.png",
122
+ ]
123
+
124
+
125
+ with gr.Blocks() as demo:
126
+ with gr.Column(elem_id="col-container"):
127
+ gr.Image("assets/logo.png", width=600)
128
+ with gr.Row():
129
+ with gr.Column():
130
+ input_image = gr.Image(label="Input Image", image_mode="RGBA")
131
+
132
+ with gr.Column():
133
+ seed = gr.Slider(
134
+ label="Seed",
135
+ minimum=0,
136
+ maximum=MAX_SEED,
137
+ step=1,
138
+ value=0,
139
+ )
140
+
141
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
142
+
143
+
144
+ prompt = gr.Textbox(
145
+ label="Prompt (Optional)",
146
+ placeholder="Please enter the prompt to guide the decomposition (Optional)",
147
+ value="",
148
+ lines=2,
149
+ )
150
+ neg_prompt = gr.Textbox(
151
+ label="Negative Prompt (Optional)",
152
+ placeholder="Please enter the negative prompt",
153
+ value=" ",
154
+ lines=2,
155
+ )
156
+
157
+ with gr.Row():
158
+ true_guidance_scale = gr.Slider(
159
+ label="True guidance scale",
160
+ minimum=1.0,
161
+ maximum=10.0,
162
+ step=0.1,
163
+ value=4.0
164
+ )
165
+
166
+ num_inference_steps = gr.Slider(
167
+ label="Number of inference steps",
168
+ minimum=1,
169
+ maximum=50,
170
+ step=1,
171
+ value=50,
172
+ )
173
+
174
+ layer = gr.Slider(
175
+ label="Layers",
176
+ minimum=2,
177
+ maximum=10,
178
+ step=1,
179
+ value=4,
180
+ )
181
+
182
+ with gr.Row():
183
+ cfg_norm = gr.Checkbox(label="Whether enable CFG normalization", value=True)
184
+ use_en_prompt = gr.Checkbox(label="Automatic caption language if no prompt provided, True for EN, False for ZH", value=True)
185
+
186
+ with gr.Row():
187
+ run_button = gr.Button("Decompose!", variant="primary")
188
+
189
+ gallery = gr.Gallery(label="Layers", columns=4, rows=1, format="png")
190
+ export_btn = gr.Button("Export as PPTX")
191
+ export_file = gr.File(label="Download PPTX")
192
+ export_btn.click(
193
+ fn=export_gallery,
194
+ inputs=gallery,
195
+ outputs=export_file
196
+ )
197
+
198
+ gr.Examples(examples=examples,
199
+ inputs=[input_image],
200
+ outputs=[gallery],
201
+ fn=infer,
202
+ examples_per_page=14,
203
+ cache_examples=False,
204
+ run_on_click=True
205
+ )
206
+
207
+ run_button.click(
208
+ fn=infer,
209
+ inputs=[
210
+ input_image,
211
+ seed,
212
+ randomize_seed,
213
+ prompt,
214
+ neg_prompt,
215
+ true_guidance_scale,
216
+ num_inference_steps,
217
+ layer,
218
+ cfg_norm,
219
+ use_en_prompt,
220
+ ],
221
+ outputs=gallery,
222
+ )
223
+
224
+ if __name__ == "__main__":
225
+ demo.launch()