Spaces:
Running on Zero
Running on Zero
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,6 +9,7 @@ from PIL import Image
|
|
| 9 |
from typing import Iterable
|
| 10 |
from gradio.themes import Soft
|
| 11 |
from gradio.themes.utils import colors, fonts, sizes
|
|
|
|
| 12 |
|
| 13 |
colors.orange_red = colors.Color(
|
| 14 |
name="orange_red",
|
|
@@ -130,15 +131,10 @@ def update_dimensions_on_upload(image):
|
|
| 130 |
return new_width, new_height
|
| 131 |
|
| 132 |
@spaces.GPU
|
| 133 |
-
def
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
randomize_seed,
|
| 138 |
-
guidance_scale,
|
| 139 |
-
steps,
|
| 140 |
-
progress=gr.Progress(track_tqdm=True)
|
| 141 |
-
):
|
| 142 |
gc.collect()
|
| 143 |
torch.cuda.empty_cache()
|
| 144 |
|
|
@@ -187,7 +183,8 @@ def infer(
|
|
| 187 |
true_cfg_scale=guidance_scale,
|
| 188 |
).images[0]
|
| 189 |
|
| 190 |
-
|
|
|
|
| 191 |
|
| 192 |
except Exception as e:
|
| 193 |
raise e
|
|
@@ -195,25 +192,37 @@ def infer(
|
|
| 195 |
gc.collect()
|
| 196 |
torch.cuda.empty_cache()
|
| 197 |
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
else:
|
| 206 |
-
images_list = images
|
| 207 |
-
|
| 208 |
-
result, seed = infer(
|
| 209 |
-
images=images_list,
|
| 210 |
-
prompt=prompt,
|
| 211 |
-
seed=0,
|
| 212 |
-
randomize_seed=True,
|
| 213 |
-
guidance_scale=1.0,
|
| 214 |
-
steps=4
|
| 215 |
)
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 217 |
|
| 218 |
css = """
|
| 219 |
#col-container {
|
|
@@ -232,7 +241,6 @@ with gr.Blocks() as demo:
|
|
| 232 |
with gr.Column():
|
| 233 |
images = gr.Gallery(
|
| 234 |
label="Upload Images",
|
| 235 |
-
#sources=["upload", "clipboard"],
|
| 236 |
type="filepath",
|
| 237 |
columns=2,
|
| 238 |
rows=1,
|
|
@@ -250,7 +258,9 @@ with gr.Blocks() as demo:
|
|
| 250 |
run_button = gr.Button("Edit Image", variant="primary")
|
| 251 |
|
| 252 |
with gr.Column():
|
| 253 |
-
output_image = gr.Image(label="Output Image", interactive=False, format="png"
|
|
|
|
|
|
|
| 254 |
|
| 255 |
with gr.Accordion("Advanced Settings", open=False, visible=False):
|
| 256 |
seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
|
|
@@ -258,28 +268,12 @@ with gr.Blocks() as demo:
|
|
| 258 |
guidance_scale = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=10.0, step=0.1, value=1.0)
|
| 259 |
steps = gr.Slider(label="Inference Steps", minimum=1, maximum=50, step=1, value=4)
|
| 260 |
|
| 261 |
-
gr.Examples(
|
| 262 |
-
examples=[
|
| 263 |
-
[["examples/1.jpg"], "cinematic polaroid with soft grain subtle vignette gentle lighting white frame handwritten photographed 'Fire-Edit' preserving realistic texture and details."],
|
| 264 |
-
[["examples/2.jpg"], "Transform the image into a dotted cartoon style."],
|
| 265 |
-
[["examples/3.jpeg"], "Convert it to black and white."],
|
| 266 |
-
[["examples/4.jpg", "examples/5.jpg"], "Replace her glasses with the new glasses from image 1."],
|
| 267 |
-
[["examples/8.jpg", "examples/9.png"], "Replace the current clothing with the clothing from the reference image 2. Keep the person’s face, hairstyle, body pose, background, lighting, and camera angle unchanged. Ensure the new outfit fits naturally with realistic fabric texture, proper shadows, folds, and accurate proportions. Match the lighting, color tone, and overall style for a seamless and high-quality result."],
|
| 268 |
-
[["examples/10.jpg", "examples/11.png"], "Replace the current clothing with the clothing from the reference image 2. Keep the person’s face, hairstyle, body pose, background, lighting, and camera angle unchanged. Ensure the new outfit fits naturally with realistic fabric texture, proper shadows, folds, and accurate proportions. Match the lighting, color tone, and overall style for a seamless and high-quality result."],
|
| 269 |
-
],
|
| 270 |
-
inputs=[images, prompt],
|
| 271 |
-
outputs=[output_image, seed],
|
| 272 |
-
fn=infer_example,
|
| 273 |
-
cache_examples=False,
|
| 274 |
-
label="Examples"
|
| 275 |
-
)
|
| 276 |
-
|
| 277 |
gr.Markdown("[*](https://huggingface.co/FireRedTeam/FireRed-Image-Edit-1.0)This is still an experimental Space for FireRed-Image-Edit-1.0.")
|
| 278 |
|
| 279 |
run_button.click(
|
| 280 |
-
fn=
|
| 281 |
inputs=[images, prompt, seed, randomize_seed, guidance_scale, steps],
|
| 282 |
-
outputs=[output_image, seed]
|
| 283 |
)
|
| 284 |
|
| 285 |
if __name__ == "__main__":
|
|
|
|
| 9 |
from typing import Iterable
|
| 10 |
from gradio.themes import Soft
|
| 11 |
from gradio.themes.utils import colors, fonts, sizes
|
| 12 |
+
from datetime import datetime
|
| 13 |
|
| 14 |
colors.orange_red = colors.Color(
|
| 15 |
name="orange_red",
|
|
|
|
| 131 |
return new_width, new_height
|
| 132 |
|
| 133 |
@spaces.GPU
|
| 134 |
+
def run_gpu_inference(images, prompt, seed, randomize_seed, guidance_scale, steps):
|
| 135 |
+
"""
|
| 136 |
+
负责在 ZeroGPU 上运行模型推理,运行完毕后返回结果并自动释放 GPU
|
| 137 |
+
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
gc.collect()
|
| 139 |
torch.cuda.empty_cache()
|
| 140 |
|
|
|
|
| 183 |
true_cfg_scale=guidance_scale,
|
| 184 |
).images[0]
|
| 185 |
|
| 186 |
+
# 返回:生成的结果图,最终使用的 seed,以及被用作底图的第一张原始图片
|
| 187 |
+
return result_image, seed, pil_images[0]
|
| 188 |
|
| 189 |
except Exception as e:
|
| 190 |
raise e
|
|
|
|
| 192 |
gc.collect()
|
| 193 |
torch.cuda.empty_cache()
|
| 194 |
|
| 195 |
+
def process_and_concat(images, prompt, seed, randomize_seed, guidance_scale, steps, progress=gr.Progress(track_tqdm=True)):
|
| 196 |
+
"""
|
| 197 |
+
负责调用 GPU 推理,等待 GPU 释放后,在 CPU 环境下完成上下拼接并生成规范命名的无损图片。
|
| 198 |
+
"""
|
| 199 |
+
# 1. 执行 GPU 推理 (此函数运行完毕后,ZeroGPU 即会关闭/释放)
|
| 200 |
+
result_image, final_seed, orig_image = run_gpu_inference(
|
| 201 |
+
images, prompt, seed, randomize_seed, guidance_scale, steps
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
)
|
| 203 |
+
|
| 204 |
+
# 2. 修改前后上下拼接 (在 CPU 上进行)
|
| 205 |
+
# 为了保证拼接整齐,将原图 resize 为与结果图完全一致的尺寸
|
| 206 |
+
orig_resized = orig_image.resize((result_image.width, result_image.height), Image.Resampling.LANCZOS)
|
| 207 |
+
|
| 208 |
+
total_width = result_image.width
|
| 209 |
+
total_height = orig_resized.height + result_image.height
|
| 210 |
+
|
| 211 |
+
concat_img = Image.new('RGB', (total_width, total_height))
|
| 212 |
+
# 上:原图
|
| 213 |
+
concat_img.paste(orig_resized, (0, 0))
|
| 214 |
+
# 下:修改后的图
|
| 215 |
+
concat_img.paste(result_image, (0, orig_resized.height))
|
| 216 |
+
|
| 217 |
+
# 3. 保存为规范命名的无损 PNG 格式
|
| 218 |
+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
| 219 |
+
filename = f"[edit]_{timestamp}_seed{final_seed}.png"
|
| 220 |
+
filepath = os.path.join(os.getcwd(), filename)
|
| 221 |
+
concat_img.save(filepath, format="PNG")
|
| 222 |
+
|
| 223 |
+
# 返回拼接后的预览图,提供下载的文件路径,以及 seed
|
| 224 |
+
return concat_img, filepath, final_seed
|
| 225 |
+
|
| 226 |
|
| 227 |
css = """
|
| 228 |
#col-container {
|
|
|
|
| 241 |
with gr.Column():
|
| 242 |
images = gr.Gallery(
|
| 243 |
label="Upload Images",
|
|
|
|
| 244 |
type="filepath",
|
| 245 |
columns=2,
|
| 246 |
rows=1,
|
|
|
|
| 258 |
run_button = gr.Button("Edit Image", variant="primary")
|
| 259 |
|
| 260 |
with gr.Column():
|
| 261 |
+
output_image = gr.Image(label="Output Image (Top: Before, Bottom: After)", interactive=False, format="png")
|
| 262 |
+
# 新增用于一键下载无损图的组件
|
| 263 |
+
output_file = gr.File(label="Download Lossless Merged Image")
|
| 264 |
|
| 265 |
with gr.Accordion("Advanced Settings", open=False, visible=False):
|
| 266 |
seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
|
|
|
|
| 268 |
guidance_scale = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=10.0, step=0.1, value=1.0)
|
| 269 |
steps = gr.Slider(label="Inference Steps", minimum=1, maximum=50, step=1, value=4)
|
| 270 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
gr.Markdown("[*](https://huggingface.co/FireRedTeam/FireRed-Image-Edit-1.0)This is still an experimental Space for FireRed-Image-Edit-1.0.")
|
| 272 |
|
| 273 |
run_button.click(
|
| 274 |
+
fn=process_and_concat,
|
| 275 |
inputs=[images, prompt, seed, randomize_seed, guidance_scale, steps],
|
| 276 |
+
outputs=[output_image, output_file, seed]
|
| 277 |
)
|
| 278 |
|
| 279 |
if __name__ == "__main__":
|