opsiclear-admin commited on
Commit
b78d4b6
·
verified ·
1 Parent(s): 20aab2a

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +41 -26
app.py CHANGED
@@ -380,7 +380,6 @@ def preprocess_image(input: Image.Image) -> Image.Image:
380
  return output
381
 
382
 
383
- @spaces.GPU(duration=60)
384
  def preprocess_images(images):
385
  """
386
  Preprocess a list of input images for multi-image conditioning.
@@ -483,8 +482,18 @@ def split_image(image: Image.Image) -> List[Image.Image]:
483
  return [preprocess_image(image) for image in images]
484
 
485
 
486
- @spaces.GPU(duration=120)
 
 
 
 
 
 
 
 
 
487
  def image_to_3d(
 
488
  seed,
489
  resolution,
490
  ss_guidance_strength,
@@ -499,19 +508,11 @@ def image_to_3d(
499
  tex_slat_guidance_rescale,
500
  tex_slat_sampling_steps,
501
  tex_slat_rescale_t,
502
- multiimages,
503
  multiimage_algo,
504
  tex_multiimage_algo,
505
  req: gr.Request,
506
  progress=gr.Progress(track_tqdm=True),
507
  ):
508
- if not multiimages:
509
- raise gr.Error("Please upload images or select an example first.")
510
-
511
- # Preprocess images (background removal, cropping, etc.)
512
- images = [image[0] for image in multiimages]
513
- processed_images = [preprocess_image(img) for img in images]
514
-
515
  # --- Sampling ---
516
  outputs, latents = pipeline.run_multi_image(
517
  processed_images,
@@ -546,15 +547,19 @@ def image_to_3d(
546
  )
547
  mesh = outputs[0]
548
  mesh.simplify(16777216) # nvdiffrast limit
549
- images = render_utils.render_snapshot(mesh, resolution=1024, r=2, fov=36, nviews=STEPS, envmap=envmap)
550
  state = pack_state(latents)
551
  torch.cuda.empty_cache()
 
 
552
 
553
- # --- HTML Construction ---
554
- # The Stack of 48 Images - encode in parallel for speed
 
 
555
  def encode_preview_image(args):
556
  m_idx, s_idx, render_key = args
557
- img_base64 = image_to_base64(Image.fromarray(images[render_key][s_idx]))
558
  return (m_idx, s_idx, img_base64)
559
 
560
  encode_tasks = [
@@ -587,7 +592,6 @@ def image_to_3d(
587
  btns_html = ""
588
  for idx, mode in enumerate(MODES):
589
  active_class = "active" if idx == DEFAULT_MODE else ""
590
- # Note: onclick calls the JS function defined in Head
591
  btns_html += f"""
592
  <img src="{mode['icon_base64']}"
593
  class="mode-btn {active_class}"
@@ -626,7 +630,7 @@ def image_to_3d(
626
  return state, full_html
627
 
628
 
629
- @spaces.GPU(duration=120)
630
  def extract_glb(
631
  state,
632
  decimation_target,
@@ -675,18 +679,19 @@ def extract_glb(
675
 
676
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", neutral_hue="slate"), css=css, head=head) as demo:
677
  gr.HTML("""
678
- <div style="display: flex; align-items: center; gap: 20px; margin-bottom: 10px;">
679
- <a href="https://www.opsiclear.com" target="_blank">
680
- <img src="https://www.opsiclear.com/assets/logos/Logo_v2_compact_name.svg" alt="OpsiClear" style="height: 80px;">
 
681
  </a>
682
- <div>
683
- <h2 style="margin: 0;">Multi-View to 3D with <a href="https://microsoft.github.io/TRELLIS.2" target="_blank">TRELLIS.2</a></h2>
684
- <ul style="margin: 5px 0; padding-left: 20px;">
685
  <li>Upload multiple images from different viewpoints to create a 3D asset with multi-image conditioning.</li>
686
  <li>Click an example below to load a pre-made multi-view set, or upload your own images.</li>
687
  <li>Click <b>Generate</b> to create the 3D model, then <b>Extract GLB</b> to export.</li>
688
- <li style="color: #e67300;"><b>⚠️ Note:</b> Generation quality is highly sensitive to parameters. Adjust settings in Advanced Settings if results are unsatisfactory.</li>
689
- <li style="color: #cc3333;"><b>⚠️ Non-Commercial:</b> This space uses models with licenses that <b>forbid commercial use</b> (BRIA RMBG-2.0: CC BY-NC 4.0, nvdiffrast/nvdiffrec: NVIDIA Source Code License).</li>
690
  </ul>
691
  </div>
692
  </div>
@@ -745,6 +750,8 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", neutral_hue="slate"),
745
  )
746
 
747
  output_buf = gr.State()
 
 
748
 
749
 
750
  # Handlers
@@ -760,15 +767,23 @@ with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", neutral_hue="slate"),
760
  get_seed,
761
  inputs=[randomize_seed, seed],
762
  outputs=[seed],
 
 
 
 
763
  ).then(
764
  image_to_3d,
765
  inputs=[
766
- seed, resolution,
767
  ss_guidance_strength, ss_guidance_rescale, ss_sampling_steps, ss_rescale_t,
768
  shape_slat_guidance_strength, shape_slat_guidance_rescale, shape_slat_sampling_steps, shape_slat_rescale_t,
769
  tex_slat_guidance_strength, tex_slat_guidance_rescale, tex_slat_sampling_steps, tex_slat_rescale_t,
770
- multiimage_prompt, multiimage_algo, tex_multiimage_algo
771
  ],
 
 
 
 
772
  outputs=[output_buf, preview_output],
773
  )
774
 
 
380
  return output
381
 
382
 
 
383
  def preprocess_images(images):
384
  """
385
  Preprocess a list of input images for multi-image conditioning.
 
482
  return [preprocess_image(image) for image in images]
483
 
484
 
485
+ def preprocess_for_generate(multiimages):
486
+ """Preprocess images before GPU generation. No GPU needed — background
487
+ removal is a network call to the BRIA RMBG Space."""
488
+ if not multiimages:
489
+ raise gr.Error("Please upload images or select an example first.")
490
+ images = [image[0] for image in multiimages]
491
+ return [preprocess_image(img) for img in images]
492
+
493
+
494
+ @spaces.GPU(duration=180)
495
  def image_to_3d(
496
+ processed_images,
497
  seed,
498
  resolution,
499
  ss_guidance_strength,
 
508
  tex_slat_guidance_rescale,
509
  tex_slat_sampling_steps,
510
  tex_slat_rescale_t,
 
511
  multiimage_algo,
512
  tex_multiimage_algo,
513
  req: gr.Request,
514
  progress=gr.Progress(track_tqdm=True),
515
  ):
 
 
 
 
 
 
 
516
  # --- Sampling ---
517
  outputs, latents = pipeline.run_multi_image(
518
  processed_images,
 
547
  )
548
  mesh = outputs[0]
549
  mesh.simplify(16777216) # nvdiffrast limit
550
+ render_images = render_utils.render_snapshot(mesh, resolution=1024, r=2, fov=36, nviews=STEPS, envmap=envmap)
551
  state = pack_state(latents)
552
  torch.cuda.empty_cache()
553
+ return state, render_images
554
+
555
 
556
+ def build_preview_html(state, render_images):
557
+ """Encode rendered images to base64 and build the HTML preview.
558
+ No GPU needed — pure CPU work."""
559
+ # Encode 48 images in parallel
560
  def encode_preview_image(args):
561
  m_idx, s_idx, render_key = args
562
+ img_base64 = image_to_base64(Image.fromarray(render_images[render_key][s_idx]))
563
  return (m_idx, s_idx, img_base64)
564
 
565
  encode_tasks = [
 
592
  btns_html = ""
593
  for idx, mode in enumerate(MODES):
594
  active_class = "active" if idx == DEFAULT_MODE else ""
 
595
  btns_html += f"""
596
  <img src="{mode['icon_base64']}"
597
  class="mode-btn {active_class}"
 
630
  return state, full_html
631
 
632
 
633
+ @spaces.GPU(duration=180)
634
  def extract_glb(
635
  state,
636
  decimation_target,
 
679
 
680
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="orange", neutral_hue="slate"), css=css, head=head) as demo:
681
  gr.HTML("""
682
+ <div style="display: flex; align-items: flex-start; gap: 24px; padding: 16px 20px; margin-bottom: 12px; border-radius: 12px; background: var(--block-background-fill); border: 1px solid var(--border-color-primary);">
683
+ <a href="https://www.opsiclear.com" target="_blank" style="flex-shrink: 0; display: flex; align-items: center;">
684
+ <img src="https://www.opsiclear.com/assets/logos/Logo_v2_compact_name.svg" alt="OpsiClear"
685
+ style="width: 72px; height: 72px; object-fit: contain;">
686
  </a>
687
+ <div style="min-width: 0;">
688
+ <h2 style="margin: 0 0 8px 0; font-size: 1.25rem; line-height: 1.3;">Multi-View to 3D with <a href="https://microsoft.github.io/TRELLIS.2" target="_blank" style="text-decoration: none; color: var(--color-accent);">TRELLIS.2</a></h2>
689
+ <ul style="margin: 0; padding-left: 18px; font-size: 0.9rem; line-height: 1.6; color: var(--body-text-color-subdued, var(--body-text-color));">
690
  <li>Upload multiple images from different viewpoints to create a 3D asset with multi-image conditioning.</li>
691
  <li>Click an example below to load a pre-made multi-view set, or upload your own images.</li>
692
  <li>Click <b>Generate</b> to create the 3D model, then <b>Extract GLB</b> to export.</li>
693
+ <li style="color: #e67300;"><b>Note:</b> Generation quality is highly sensitive to parameters. Adjust settings in Advanced Settings if results are unsatisfactory.</li>
694
+ <li style="color: #cc3333;"><b>Non-Commercial:</b> This space uses models with licenses that <b>forbid commercial use</b> (BRIA RMBG-2.0: CC BY-NC 4.0, nvdiffrast/nvdiffrec: NVIDIA Source Code License).</li>
695
  </ul>
696
  </div>
697
  </div>
 
750
  )
751
 
752
  output_buf = gr.State()
753
+ processed_buf = gr.State()
754
+ render_buf = gr.State()
755
 
756
 
757
  # Handlers
 
767
  get_seed,
768
  inputs=[randomize_seed, seed],
769
  outputs=[seed],
770
+ ).then(
771
+ preprocess_for_generate,
772
+ inputs=[multiimage_prompt],
773
+ outputs=[processed_buf],
774
  ).then(
775
  image_to_3d,
776
  inputs=[
777
+ processed_buf, seed, resolution,
778
  ss_guidance_strength, ss_guidance_rescale, ss_sampling_steps, ss_rescale_t,
779
  shape_slat_guidance_strength, shape_slat_guidance_rescale, shape_slat_sampling_steps, shape_slat_rescale_t,
780
  tex_slat_guidance_strength, tex_slat_guidance_rescale, tex_slat_sampling_steps, tex_slat_rescale_t,
781
+ multiimage_algo, tex_multiimage_algo
782
  ],
783
+ outputs=[output_buf, render_buf],
784
+ ).then(
785
+ build_preview_html,
786
+ inputs=[output_buf, render_buf],
787
  outputs=[output_buf, preview_output],
788
  )
789