Spaces:
Running on Zero
Running on Zero
Fix diso undefined symbol (clone with --recurse-submodules); remove RMBG preview/controls from UI
Browse files
app.py
CHANGED
|
@@ -45,9 +45,10 @@ _NO_DEPS_PACKAGES = [
|
|
| 45 |
]
|
| 46 |
|
| 47 |
# 3. Packages requiring nvcc (CUDA compiler only in runtime GPU containers)
|
|
|
|
|
|
|
| 48 |
_CUDA_PACKAGES = [
|
| 49 |
"nvdiffrast @ git+https://github.com/NVlabs/nvdiffrast.git@253ac4fcea7de5f396371124af597e6cc957bfae",
|
| 50 |
-
"diso @ git+https://github.com/SarahWeiii/diso.git@9792ad928ccb09bdec938779651ee03e395758a6",
|
| 51 |
"detectron2 @ git+https://github.com/facebookresearch/detectron2.git@8a9d885b3d4dcf1bef015f0593b872ed8d32b4ab",
|
| 52 |
]
|
| 53 |
|
|
@@ -83,6 +84,20 @@ def _install_runtime_packages():
|
|
| 83 |
[sys.executable, "-m", "pip", "install", "--quiet", "--no-build-isolation"]
|
| 84 |
+ _CUDA_PACKAGES, env=_cuda_env, check=True,
|
| 85 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
_RUNTIME_PKG_MARKER.touch()
|
| 87 |
print("[startup] Runtime packages installed.")
|
| 88 |
|
|
@@ -174,6 +189,35 @@ def load_triposg():
|
|
| 174 |
if str(triposg_src) not in sys.path:
|
| 175 |
sys.path.insert(0, str(triposg_src))
|
| 176 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
weights_path = snapshot_download("VAST-AI/TripoSG")
|
| 178 |
|
| 179 |
from triposg.pipelines.pipeline_triposg import TripoSGPipeline
|
|
@@ -593,17 +637,16 @@ def render_views(glb_file):
|
|
| 593 |
|
| 594 |
# ββ Full pipeline βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 595 |
|
| 596 |
-
def run_full_pipeline(input_image,
|
| 597 |
-
variant, tex_seed, enhance_face,
|
| 598 |
export_fbx, mdm_prompt, mdm_n_frames, progress=gr.Progress()):
|
| 599 |
progress(0.0, desc="Stage 1/3: Generating shape...")
|
| 600 |
-
glb, status = generate_shape(input_image,
|
| 601 |
if not glb:
|
| 602 |
return None, None, None, None, None, None, status
|
| 603 |
|
| 604 |
progress(0.33, desc="Stage 2/3: Applying texture...")
|
| 605 |
-
glb, mv_img, status = apply_texture(glb, input_image,
|
| 606 |
-
enhance_face, rembg_threshold, rembg_erode)
|
| 607 |
if not glb:
|
| 608 |
return None, None, None, None, None, None, status
|
| 609 |
|
|
@@ -626,12 +669,6 @@ with gr.Blocks(title="Image2Model") as demo:
|
|
| 626 |
with gr.Row():
|
| 627 |
with gr.Column(scale=1):
|
| 628 |
input_image = gr.Image(label="Input Image", type="numpy")
|
| 629 |
-
remove_bg_check = gr.Checkbox(label="Remove Background", value=True)
|
| 630 |
-
with gr.Row():
|
| 631 |
-
rembg_threshold = gr.Slider(0.1, 0.95, value=0.5, step=0.05,
|
| 632 |
-
label="BG Threshold")
|
| 633 |
-
rembg_erode = gr.Slider(0, 8, value=2, step=1,
|
| 634 |
-
label="Edge Erode (px)")
|
| 635 |
|
| 636 |
with gr.Accordion("Shape Settings", open=True):
|
| 637 |
num_steps = gr.Slider(20, 100, value=50, step=5, label="Inference Steps")
|
|
@@ -653,7 +690,6 @@ with gr.Blocks(title="Image2Model") as demo:
|
|
| 653 |
run_all_btn = gr.Button("βΆ Run Full Pipeline", variant="primary", interactive=False)
|
| 654 |
|
| 655 |
with gr.Column(scale=1):
|
| 656 |
-
rembg_preview = gr.Image(label="BG Removed Preview", type="numpy", interactive=False)
|
| 657 |
status = gr.Textbox(label="Status", lines=3, interactive=False)
|
| 658 |
model_3d = gr.Model3D(label="3D Preview", clear_color=[0.9, 0.9, 0.9, 1.0])
|
| 659 |
download_file = gr.File(label="Download GLB")
|
|
@@ -661,7 +697,6 @@ with gr.Blocks(title="Image2Model") as demo:
|
|
| 661 |
|
| 662 |
render_gallery = gr.Gallery(label="Rendered Views", columns=5, height=300)
|
| 663 |
|
| 664 |
-
_rembg_inputs = [input_image, remove_bg_check, rembg_threshold, rembg_erode]
|
| 665 |
_pipeline_btns = [shape_btn, run_all_btn]
|
| 666 |
|
| 667 |
input_image.upload(
|
|
@@ -672,14 +707,10 @@ with gr.Blocks(title="Image2Model") as demo:
|
|
| 672 |
fn=lambda: (gr.update(interactive=False), gr.update(interactive=False)),
|
| 673 |
inputs=[], outputs=_pipeline_btns,
|
| 674 |
)
|
| 675 |
-
input_image.upload(fn=preview_rembg, inputs=_rembg_inputs, outputs=[rembg_preview])
|
| 676 |
-
remove_bg_check.change(fn=preview_rembg, inputs=_rembg_inputs, outputs=[rembg_preview])
|
| 677 |
-
rembg_threshold.release(fn=preview_rembg, inputs=_rembg_inputs, outputs=[rembg_preview])
|
| 678 |
-
rembg_erode.release(fn=preview_rembg, inputs=_rembg_inputs, outputs=[rembg_preview])
|
| 679 |
|
| 680 |
shape_btn.click(
|
| 681 |
-
fn=generate_shape,
|
| 682 |
-
inputs=[input_image,
|
| 683 |
outputs=[glb_state, status],
|
| 684 |
).then(
|
| 685 |
fn=lambda p: (p, p) if p else (None, None),
|
|
@@ -687,9 +718,8 @@ with gr.Blocks(title="Image2Model") as demo:
|
|
| 687 |
)
|
| 688 |
|
| 689 |
texture_btn.click(
|
| 690 |
-
fn=apply_texture,
|
| 691 |
-
inputs=[glb_state, input_image,
|
| 692 |
-
enhance_face_check, rembg_threshold, rembg_erode],
|
| 693 |
outputs=[glb_state, multiview_img, status],
|
| 694 |
).then(
|
| 695 |
fn=lambda p: (p, p) if p else (None, None),
|
|
@@ -791,8 +821,8 @@ with gr.Blocks(title="Image2Model") as demo:
|
|
| 791 |
run_all_btn.click(
|
| 792 |
fn=run_full_pipeline,
|
| 793 |
inputs=[
|
| 794 |
-
input_image,
|
| 795 |
-
variant, tex_seed, enhance_face_check,
|
| 796 |
export_fbx_check, mdm_prompt_box, mdm_frames_slider,
|
| 797 |
],
|
| 798 |
outputs=[glb_state, download_file, multiview_img,
|
|
|
|
| 45 |
]
|
| 46 |
|
| 47 |
# 3. Packages requiring nvcc (CUDA compiler only in runtime GPU containers)
|
| 48 |
+
# NOTE: diso is NOT listed here β it's cloned with --recurse-submodules below
|
| 49 |
+
# because pip install git+... doesn't fetch submodules, causing undefined symbols.
|
| 50 |
_CUDA_PACKAGES = [
|
| 51 |
"nvdiffrast @ git+https://github.com/NVlabs/nvdiffrast.git@253ac4fcea7de5f396371124af597e6cc957bfae",
|
|
|
|
| 52 |
"detectron2 @ git+https://github.com/facebookresearch/detectron2.git@8a9d885b3d4dcf1bef015f0593b872ed8d32b4ab",
|
| 53 |
]
|
| 54 |
|
|
|
|
| 84 |
[sys.executable, "-m", "pip", "install", "--quiet", "--no-build-isolation"]
|
| 85 |
+ _CUDA_PACKAGES, env=_cuda_env, check=True,
|
| 86 |
)
|
| 87 |
+
# diso: pip install git+... does not fetch git submodules, causing undefined
|
| 88 |
+
# CUDA symbols at import time. Clone with --recurse-submodules first.
|
| 89 |
+
_diso_src = Path("/tmp/diso-build")
|
| 90 |
+
if not _diso_src.exists():
|
| 91 |
+
subprocess.run(
|
| 92 |
+
["git", "clone", "--recurse-submodules", "--depth=1",
|
| 93 |
+
"https://github.com/SarahWeiii/diso.git", str(_diso_src)],
|
| 94 |
+
env=_cuda_env, check=True,
|
| 95 |
+
)
|
| 96 |
+
subprocess.run(
|
| 97 |
+
[sys.executable, "-m", "pip", "install", "--quiet", "--no-build-isolation",
|
| 98 |
+
str(_diso_src)],
|
| 99 |
+
env=_cuda_env, check=True,
|
| 100 |
+
)
|
| 101 |
_RUNTIME_PKG_MARKER.touch()
|
| 102 |
print("[startup] Runtime packages installed.")
|
| 103 |
|
|
|
|
| 189 |
if str(triposg_src) not in sys.path:
|
| 190 |
sys.path.insert(0, str(triposg_src))
|
| 191 |
|
| 192 |
+
# Safety net: patch inference_utils.py to make diso import optional.
|
| 193 |
+
# Even if diso compiled with submodules, guard against any residual link errors.
|
| 194 |
+
_iu_path = triposg_src / "triposg" / "inference_utils.py"
|
| 195 |
+
if _iu_path.exists():
|
| 196 |
+
_iu_text = _iu_path.read_text()
|
| 197 |
+
if "DiffDMC = None" not in _iu_text and "from diso import DiffDMC" in _iu_text:
|
| 198 |
+
_iu_text = _iu_text.replace(
|
| 199 |
+
"from diso import DiffDMC",
|
| 200 |
+
"try:\n from diso import DiffDMC\n"
|
| 201 |
+
"except Exception as _diso_err:\n"
|
| 202 |
+
" print(f'[TripoSG] diso unavailable ({_diso_err}), using flash fallback')\n"
|
| 203 |
+
" DiffDMC = None",
|
| 204 |
+
)
|
| 205 |
+
if ("def hierarchical_extract_geometry(" in _iu_text
|
| 206 |
+
and "flash_extract_geometry" in _iu_text):
|
| 207 |
+
_iu_text = _iu_text.replace(
|
| 208 |
+
"def hierarchical_extract_geometry(",
|
| 209 |
+
"def _hierarchical_extract_geometry_impl(",
|
| 210 |
+
)
|
| 211 |
+
_iu_text += (
|
| 212 |
+
"\n\n"
|
| 213 |
+
"def hierarchical_extract_geometry(*args, **kwargs):\n"
|
| 214 |
+
" if DiffDMC is None:\n"
|
| 215 |
+
" return flash_extract_geometry(*args, **kwargs)\n"
|
| 216 |
+
" return _hierarchical_extract_geometry_impl(*args, **kwargs)\n"
|
| 217 |
+
)
|
| 218 |
+
_iu_path.write_text(_iu_text)
|
| 219 |
+
print("[load_triposg] Patched inference_utils.py: diso optional")
|
| 220 |
+
|
| 221 |
weights_path = snapshot_download("VAST-AI/TripoSG")
|
| 222 |
|
| 223 |
from triposg.pipelines.pipeline_triposg import TripoSGPipeline
|
|
|
|
| 637 |
|
| 638 |
# ββ Full pipeline βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 639 |
|
| 640 |
+
def run_full_pipeline(input_image, num_steps, guidance, seed, face_count,
|
| 641 |
+
variant, tex_seed, enhance_face,
|
| 642 |
export_fbx, mdm_prompt, mdm_n_frames, progress=gr.Progress()):
|
| 643 |
progress(0.0, desc="Stage 1/3: Generating shape...")
|
| 644 |
+
glb, status = generate_shape(input_image, True, num_steps, guidance, seed, face_count)
|
| 645 |
if not glb:
|
| 646 |
return None, None, None, None, None, None, status
|
| 647 |
|
| 648 |
progress(0.33, desc="Stage 2/3: Applying texture...")
|
| 649 |
+
glb, mv_img, status = apply_texture(glb, input_image, True, variant, tex_seed, enhance_face)
|
|
|
|
| 650 |
if not glb:
|
| 651 |
return None, None, None, None, None, None, status
|
| 652 |
|
|
|
|
| 669 |
with gr.Row():
|
| 670 |
with gr.Column(scale=1):
|
| 671 |
input_image = gr.Image(label="Input Image", type="numpy")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 672 |
|
| 673 |
with gr.Accordion("Shape Settings", open=True):
|
| 674 |
num_steps = gr.Slider(20, 100, value=50, step=5, label="Inference Steps")
|
|
|
|
| 690 |
run_all_btn = gr.Button("βΆ Run Full Pipeline", variant="primary", interactive=False)
|
| 691 |
|
| 692 |
with gr.Column(scale=1):
|
|
|
|
| 693 |
status = gr.Textbox(label="Status", lines=3, interactive=False)
|
| 694 |
model_3d = gr.Model3D(label="3D Preview", clear_color=[0.9, 0.9, 0.9, 1.0])
|
| 695 |
download_file = gr.File(label="Download GLB")
|
|
|
|
| 697 |
|
| 698 |
render_gallery = gr.Gallery(label="Rendered Views", columns=5, height=300)
|
| 699 |
|
|
|
|
| 700 |
_pipeline_btns = [shape_btn, run_all_btn]
|
| 701 |
|
| 702 |
input_image.upload(
|
|
|
|
| 707 |
fn=lambda: (gr.update(interactive=False), gr.update(interactive=False)),
|
| 708 |
inputs=[], outputs=_pipeline_btns,
|
| 709 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 710 |
|
| 711 |
shape_btn.click(
|
| 712 |
+
fn=lambda img, ns, gs, sd, fc: generate_shape(img, True, ns, gs, sd, fc),
|
| 713 |
+
inputs=[input_image, num_steps, guidance, seed, face_count],
|
| 714 |
outputs=[glb_state, status],
|
| 715 |
).then(
|
| 716 |
fn=lambda p: (p, p) if p else (None, None),
|
|
|
|
| 718 |
)
|
| 719 |
|
| 720 |
texture_btn.click(
|
| 721 |
+
fn=lambda glb, img, v, ts, ef: apply_texture(glb, img, True, v, ts, ef),
|
| 722 |
+
inputs=[glb_state, input_image, variant, tex_seed, enhance_face_check],
|
|
|
|
| 723 |
outputs=[glb_state, multiview_img, status],
|
| 724 |
).then(
|
| 725 |
fn=lambda p: (p, p) if p else (None, None),
|
|
|
|
| 821 |
run_all_btn.click(
|
| 822 |
fn=run_full_pipeline,
|
| 823 |
inputs=[
|
| 824 |
+
input_image, num_steps, guidance, seed, face_count,
|
| 825 |
+
variant, tex_seed, enhance_face_check,
|
| 826 |
export_fbx_check, mdm_prompt_box, mdm_frames_slider,
|
| 827 |
],
|
| 828 |
outputs=[glb_state, download_file, multiview_img,
|