Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -123,29 +123,39 @@ def adjust_size_to_multiple_of_8(width: int, height: int) -> tuple[int, int]:
|
|
123 |
new_height = ((height + 7) // 8) * 8
|
124 |
return new_width, new_height
|
125 |
|
126 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
"""배경 이미지 생성 함수"""
|
128 |
try:
|
129 |
-
#
|
130 |
-
|
|
|
|
|
|
|
131 |
|
132 |
with timer("Background generation"):
|
133 |
image = pipe(
|
134 |
prompt=prompt,
|
135 |
-
width=
|
136 |
-
height=
|
137 |
num_inference_steps=8,
|
138 |
guidance_scale=4.0,
|
139 |
).images[0]
|
140 |
-
|
141 |
-
# 원본 크기로 리사이즈
|
142 |
-
if adjusted_width != width or adjusted_height != height:
|
143 |
-
image = image.resize((width, height), Image.Resampling.LANCZOS)
|
144 |
|
145 |
return image
|
146 |
except Exception as e:
|
147 |
raise gr.Error(f"Background generation failed: {str(e)}")
|
148 |
-
|
149 |
|
150 |
|
151 |
def combine_with_background(foreground: Image.Image, background: Image.Image) -> Image.Image:
|
@@ -170,7 +180,7 @@ def _gpu_process(img: Image.Image, prompt: str | BoundingBox | None) -> tuple[Im
|
|
170 |
time_log.append(f"segment: {time.time() - t0}")
|
171 |
return mask, bbox, time_log
|
172 |
|
173 |
-
def _process(img: Image.Image, prompt: str | BoundingBox | None, bg_prompt: str | None = None) -> tuple[tuple[Image.Image, Image.Image, Image.Image], gr.DownloadButton]:
|
174 |
try:
|
175 |
if img.width > 2048 or img.height > 2048:
|
176 |
orig_res = max(img.width, img.height)
|
@@ -183,7 +193,7 @@ def _process(img: Image.Image, prompt: str | BoundingBox | None, bg_prompt: str
|
|
183 |
masked_alpha = apply_mask(img, mask, defringe=True)
|
184 |
|
185 |
if bg_prompt:
|
186 |
-
background = generate_background(bg_prompt,
|
187 |
combined = combine_with_background(masked_alpha, background)
|
188 |
else:
|
189 |
combined = Image.alpha_composite(Image.new("RGBA", masked_alpha.size, "white"), masked_alpha)
|
@@ -201,8 +211,6 @@ def _process(img: Image.Image, prompt: str | BoundingBox | None, bg_prompt: str
|
|
201 |
except Exception as e:
|
202 |
raise gr.Error(f"Processing failed: {str(e)}")
|
203 |
|
204 |
-
|
205 |
-
|
206 |
def on_change_bbox(prompts: dict[str, Any] | None):
|
207 |
return gr.update(interactive=prompts is not None)
|
208 |
|
@@ -210,13 +218,13 @@ def on_change_bbox(prompts: dict[str, Any] | None):
|
|
210 |
def on_change_prompt(img: Image.Image | None, prompt: str | None, bg_prompt: str | None = None):
|
211 |
return gr.update(interactive=bool(img and prompt))
|
212 |
|
213 |
-
def process_prompt(img: Image.Image, prompt: str, bg_prompt: str | None = None) -> tuple[Image.Image, Image.Image]:
|
214 |
try:
|
215 |
if img is None or prompt.strip() == "":
|
216 |
raise gr.Error("Please provide both image and prompt")
|
217 |
|
218 |
# Process the image
|
219 |
-
results, _ = _process(img, prompt, bg_prompt)
|
220 |
|
221 |
# 합성된 이미지와 추출된 이미지만 반환
|
222 |
return results[1], results[2]
|
@@ -336,11 +344,21 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
|
|
336 |
placeholder="Enter what you want to extract...",
|
337 |
interactive=True
|
338 |
)
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
344 |
process_btn = gr.Button(
|
345 |
"Process",
|
346 |
variant="primary",
|
@@ -378,12 +396,23 @@ with gr.Blocks(theme=gr.themes.Soft(), css=css) as demo:
|
|
378 |
queue=False
|
379 |
)
|
380 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
381 |
process_btn.click(
|
382 |
fn=process_prompt,
|
383 |
-
inputs=[input_image, text_prompt, bg_prompt],
|
384 |
outputs=[combined_image, extracted_image],
|
385 |
queue=True
|
386 |
)
|
387 |
|
388 |
demo.queue(max_size=30, api_open=False)
|
389 |
-
demo.launch()
|
|
|
123 |
new_height = ((height + 7) // 8) * 8
|
124 |
return new_width, new_height
|
125 |
|
126 |
+
def calculate_dimensions(aspect_ratio: str, base_size: int = 512) -> tuple[int, int]:
|
127 |
+
"""선택된 비율에 따라 이미지 크기 계산"""
|
128 |
+
if aspect_ratio == "1:1":
|
129 |
+
return base_size, base_size
|
130 |
+
elif aspect_ratio == "16:9":
|
131 |
+
return base_size * 16 // 9, base_size
|
132 |
+
elif aspect_ratio == "9:16":
|
133 |
+
return base_size, base_size * 16 // 9
|
134 |
+
elif aspect_ratio == "4:3":
|
135 |
+
return base_size * 4 // 3, base_size
|
136 |
+
return base_size, base_size
|
137 |
+
|
138 |
+
def generate_background(prompt: str, aspect_ratio: str) -> Image.Image:
|
139 |
"""배경 이미지 생성 함수"""
|
140 |
try:
|
141 |
+
# 선택된 비율에 따라 크기 계산
|
142 |
+
width, height = calculate_dimensions(aspect_ratio)
|
143 |
+
|
144 |
+
# 8의 배수로 조정
|
145 |
+
width, height = adjust_size_to_multiple_of_8(width, height)
|
146 |
|
147 |
with timer("Background generation"):
|
148 |
image = pipe(
|
149 |
prompt=prompt,
|
150 |
+
width=width,
|
151 |
+
height=height,
|
152 |
num_inference_steps=8,
|
153 |
guidance_scale=4.0,
|
154 |
).images[0]
|
|
|
|
|
|
|
|
|
155 |
|
156 |
return image
|
157 |
except Exception as e:
|
158 |
raise gr.Error(f"Background generation failed: {str(e)}")
|
|
|
159 |
|
160 |
|
161 |
def combine_with_background(foreground: Image.Image, background: Image.Image) -> Image.Image:
|
|
|
180 |
time_log.append(f"segment: {time.time() - t0}")
|
181 |
return mask, bbox, time_log
|
182 |
|
183 |
+
def _process(img: Image.Image, prompt: str | BoundingBox | None, bg_prompt: str | None = None, aspect_ratio: str = "1:1") -> tuple[tuple[Image.Image, Image.Image, Image.Image], gr.DownloadButton]:
|
184 |
try:
|
185 |
if img.width > 2048 or img.height > 2048:
|
186 |
orig_res = max(img.width, img.height)
|
|
|
193 |
masked_alpha = apply_mask(img, mask, defringe=True)
|
194 |
|
195 |
if bg_prompt:
|
196 |
+
background = generate_background(bg_prompt, aspect_ratio)
|
197 |
combined = combine_with_background(masked_alpha, background)
|
198 |
else:
|
199 |
combined = Image.alpha_composite(Image.new("RGBA", masked_alpha.size, "white"), masked_alpha)
|
|
|
211 |
except Exception as e:
|
212 |
raise gr.Error(f"Processing failed: {str(e)}")
|
213 |
|
|
|
|
|
214 |
def on_change_bbox(prompts: dict[str, Any] | None):
|
215 |
return gr.update(interactive=prompts is not None)
|
216 |
|
|
|
218 |
def on_change_prompt(img: Image.Image | None, prompt: str | None, bg_prompt: str | None = None):
|
219 |
return gr.update(interactive=bool(img and prompt))
|
220 |
|
221 |
+
def process_prompt(img: Image.Image, prompt: str, bg_prompt: str | None = None, aspect_ratio: str = "1:1") -> tuple[Image.Image, Image.Image]:
|
222 |
try:
|
223 |
if img is None or prompt.strip() == "":
|
224 |
raise gr.Error("Please provide both image and prompt")
|
225 |
|
226 |
# Process the image
|
227 |
+
results, _ = _process(img, prompt, bg_prompt, aspect_ratio)
|
228 |
|
229 |
# 합성된 이미지와 추출된 이미지만 반환
|
230 |
return results[1], results[2]
|
|
|
344 |
placeholder="Enter what you want to extract...",
|
345 |
interactive=True
|
346 |
)
|
347 |
+
with gr.Row():
|
348 |
+
bg_prompt = gr.Textbox(
|
349 |
+
label="Background Prompt (optional)",
|
350 |
+
placeholder="Describe the background...",
|
351 |
+
interactive=True,
|
352 |
+
scale=3
|
353 |
+
)
|
354 |
+
aspect_ratio = gr.Dropdown(
|
355 |
+
choices=["1:1", "16:9", "9:16", "4:3"],
|
356 |
+
value="1:1",
|
357 |
+
label="Aspect Ratio",
|
358 |
+
interactive=True,
|
359 |
+
visible=True,
|
360 |
+
scale=1
|
361 |
+
)
|
362 |
process_btn = gr.Button(
|
363 |
"Process",
|
364 |
variant="primary",
|
|
|
396 |
queue=False
|
397 |
)
|
398 |
|
399 |
+
# bg_prompt가 비어있을 때 aspect_ratio를 비활성화하는 함수
|
400 |
+
def update_aspect_ratio(bg_prompt):
|
401 |
+
return gr.update(visible=bool(bg_prompt))
|
402 |
+
|
403 |
+
bg_prompt.change(
|
404 |
+
fn=update_aspect_ratio,
|
405 |
+
inputs=bg_prompt,
|
406 |
+
outputs=aspect_ratio,
|
407 |
+
queue=False
|
408 |
+
)
|
409 |
+
|
410 |
process_btn.click(
|
411 |
fn=process_prompt,
|
412 |
+
inputs=[input_image, text_prompt, bg_prompt, aspect_ratio],
|
413 |
outputs=[combined_image, extracted_image],
|
414 |
queue=True
|
415 |
)
|
416 |
|
417 |
demo.queue(max_size=30, api_open=False)
|
418 |
+
demo.launch()
|