luca115 commited on
Commit
6b30ccf
·
verified ·
1 Parent(s): 371c0dd

Upload folder using huggingface_hub

Browse files
Files changed (2) hide show
  1. app.py +15 -6
  2. upsampler_theme.py +0 -54
app.py CHANGED
@@ -108,6 +108,11 @@ NEG_EMB = _fetch("neg_emb.pt", Path("./neg_emb.pt"))
108
  # restoring at 2MP rather than 3.7MP gives up some of its headroom on very
109
  # large outputs. It still upscales ~4.9x from a 360x240 input.
110
  WORK_AREA = int(os.environ.get("SEEDVR2_WORK_AREA", 1920 * 1080))
 
 
 
 
 
111
 
112
  # Single-process "distributed" context. The model code routes every device
113
  # placement through common.distributed, which reads these.
@@ -160,7 +165,7 @@ def _transform():
160
  )
161
 
162
 
163
- def _duration(image, steps=1, progress=None) -> int:
164
  """Every request restores at the same working resolution (WORK_AREA), so cost
165
  tracks the step count and little else. Measured on a cold worker, then
166
  given headroom; kept as small as honesty allows, because the request is
@@ -195,7 +200,7 @@ def save_result(image):
195
 
196
  @spaces.GPU(duration=_duration)
197
  @torch.no_grad()
198
- def upscale_image(image, steps=1, progress=gr.Progress(track_tqdm=True)):
199
  if image is None:
200
  raise gr.Error("Upload an image first.")
201
 
@@ -218,8 +223,10 @@ def upscale_image(image, steps=1, progress=gr.Progress(track_tqdm=True)):
218
  runner.config.diffusion.timesteps.sampling.steps = int(steps)
219
  runner.configure_diffusion()
220
  # Fixed seed: a restorer should be deterministic for a given input, and the
221
- # knob was noise in a tool whose job is 'make this photo better'.
222
- set_seed(666, same_across_ranks=True)
 
 
223
 
224
  img = Image.open(image).convert("RGB") if isinstance(image, str) else image.convert("RGB")
225
  tensor = T.ToTensor()(img).unsqueeze(0) # (t=1, c, h, w)
@@ -246,7 +253,7 @@ def upscale_image(image, steps=1, progress=gr.Progress(track_tqdm=True)):
246
  for n, a, latent in zip(noise, aug_noise, latents)
247
  ]
248
 
249
- with torch.autocast("cuda", torch.bfloat16, enabled=True):
250
  videos = runner.inference(
251
  noises=noise, conditions=conditions, dit_offload=False, **text_embeds
252
  )
@@ -290,6 +297,8 @@ with gr.Blocks(css=UPSAMPLER_CSS, theme=UPSAMPLER_THEME) as demo:
290
  with gr.Column():
291
  image_in = gr.Image(label="Image", type="filepath")
292
  steps = gr.Slider(1, 4, value=1, step=1, label="Steps")
 
 
293
  run = gr.Button("Upscale Image", variant="primary")
294
  with gr.Column():
295
  image_out = gr.Image(label="Result", type="filepath")
@@ -298,7 +307,7 @@ with gr.Blocks(css=UPSAMPLER_CSS, theme=UPSAMPLER_THEME) as demo:
298
  # publish the endpoint as "//upscale_image".
299
  run.click(
300
  upscale_image,
301
- inputs=[image_in, steps],
302
  outputs=[image_out],
303
  api_name="upscale_image",
304
  )
 
108
  # restoring at 2MP rather than 3.7MP gives up some of its headroom on very
109
  # large outputs. It still upscales ~4.9x from a 360x240 input.
110
  WORK_AREA = int(os.environ.get("SEEDVR2_WORK_AREA", 1920 * 1080))
111
+ DEFAULT_SEED = int(os.environ.get("SEEDVR2_SEED", 666))
112
+ # Upstream runs under bf16 autocast; fp16 is an override for artifact probes.
113
+ AUTOCAST_DTYPE = {"bf16": torch.bfloat16, "fp16": torch.float16}[
114
+ os.environ.get("SEEDVR2_AUTOCAST", "bf16")
115
+ ]
116
 
117
  # Single-process "distributed" context. The model code routes every device
118
  # placement through common.distributed, which reads these.
 
165
  )
166
 
167
 
168
+ def _duration(image, steps=1, seed=0, progress=None) -> int:
169
  """Every request restores at the same working resolution (WORK_AREA), so cost
170
  tracks the step count and little else. Measured on a cold worker, then
171
  given headroom; kept as small as honesty allows, because the request is
 
200
 
201
  @spaces.GPU(duration=_duration)
202
  @torch.no_grad()
203
+ def upscale_image(image, steps=1, seed=0, progress=gr.Progress(track_tqdm=True)):
204
  if image is None:
205
  raise gr.Error("Upload an image first.")
206
 
 
223
  runner.config.diffusion.timesteps.sampling.steps = int(steps)
224
  runner.configure_diffusion()
225
  # Fixed seed: a restorer should be deterministic for a given input, and the
226
+ # knob was noise in a tool whose job is 'make this photo better'. The API
227
+ # takes an override (hidden in the UI) so artifacts can be checked across
228
+ # seeds without a redeploy.
229
+ set_seed(int(seed) if seed else DEFAULT_SEED, same_across_ranks=True)
230
 
231
  img = Image.open(image).convert("RGB") if isinstance(image, str) else image.convert("RGB")
232
  tensor = T.ToTensor()(img).unsqueeze(0) # (t=1, c, h, w)
 
253
  for n, a, latent in zip(noise, aug_noise, latents)
254
  ]
255
 
256
+ with torch.autocast("cuda", AUTOCAST_DTYPE, enabled=True):
257
  videos = runner.inference(
258
  noises=noise, conditions=conditions, dit_offload=False, **text_embeds
259
  )
 
297
  with gr.Column():
298
  image_in = gr.Image(label="Image", type="filepath")
299
  steps = gr.Slider(1, 4, value=1, step=1, label="Steps")
300
+ # API-only: 0 keeps the fixed default seed.
301
+ seed = gr.Number(value=0, precision=0, visible=False)
302
  run = gr.Button("Upscale Image", variant="primary")
303
  with gr.Column():
304
  image_out = gr.Image(label="Result", type="filepath")
 
307
  # publish the endpoint as "//upscale_image".
308
  run.click(
309
  upscale_image,
310
+ inputs=[image_in, steps, seed],
311
  outputs=[image_out],
312
  api_name="upscale_image",
313
  )
upsampler_theme.py DELETED
@@ -1,54 +0,0 @@
1
- """Shared Upsampler look-and-feel for every Upsampler/* HF Space.
2
-
3
- `create_and_push.py` uploads this file alongside each Space's app.py, so every
4
- Space imports the exact same theme, CSS, header, and footer. Keep this the
5
- single source of truth (v3 recipe): Soft indigo/purple theme, gradient primary
6
- button, Gradio's own footer hidden, 1000px max width, minimal header/footer.
7
- """
8
-
9
- import gradio as gr
10
-
11
- UPSAMPLER_THEME = gr.themes.Soft(
12
- primary_hue=gr.themes.colors.indigo,
13
- secondary_hue=gr.themes.colors.purple,
14
- neutral_hue=gr.themes.colors.slate,
15
- font=[gr.themes.GoogleFont("Inter"), "system-ui", "sans-serif"],
16
- ).set(
17
- button_primary_background_fill="linear-gradient(90deg, #6366f1 0%, #a855f7 100%)",
18
- button_primary_background_fill_hover="linear-gradient(90deg, #4f46e5 0%, #9333ea 100%)",
19
- button_primary_text_color="#ffffff",
20
- button_primary_border_color="*primary_500",
21
- )
22
-
23
- # Hide Gradio's built-in footer and keep the app narrow and centered.
24
- UPSAMPLER_CSS = """
25
- footer { display: none !important; }
26
- .gradio-container { max-width: 1000px !important; margin: 0 auto !important; }
27
- #usp-header h1 { font-size: 1.7rem; font-weight: 700; margin: 0 0 .25rem; }
28
- #usp-header p { opacity: .6; margin: 0; }
29
- #usp-footer { opacity: .5; font-size: .85rem; margin-top: 1.25rem; }
30
- #usp-footer a { text-decoration: none; }
31
- """
32
-
33
-
34
- def header_html(title: str, subtitle: str) -> str:
35
- return f"""<div id="usp-header">
36
- <h1>{title}</h1>
37
- <p>{subtitle}</p>
38
- </div>"""
39
-
40
-
41
- _LINK_STYLE = "color:#8b7cf6;font-weight:600;text-decoration:none"
42
-
43
-
44
- def footer_html(description: str, tool_url: str, tool_anchor: str) -> str:
45
- """SEO footer (v4 recipe): a short paragraph describing what the model
46
- does (unique per Space, keyword-bearing) plus the Upsampler attribution
47
- with a deep link to the matching /free-* tool on upsampler.com. No model
48
- credit/license line (the README frontmatter carries the license). Spaces
49
- target model-name queries; the site pages keep the intent queries
50
- ("free X no signup"), so the two never compete."""
51
- return f"""<div id="usp-footer">
52
- <p style="margin:0 0 10px">{description}</p>
53
- <p style="margin:0">Maintained by <a href="https://upsampler.com" target="_blank" rel="noopener" style="{_LINK_STYLE}">Upsampler</a>. Check out the <a href="{tool_url}" target="_blank" rel="noopener" style="{_LINK_STYLE}">{tool_anchor}</a>, no sign-up required.</p>
54
- </div>"""