vivekchakraverty commited on
Commit
8d3e11e
Β·
verified Β·
1 Parent(s): b1eeac5

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +167 -0
  2. requirements.txt +15 -0
app.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Hunyuan3D-2 β€” Shape-only HuggingFace Space
3
+ Uses Hunyuan3D-2mini-Turbo (0.6 B, step-distilled) for fast shape generation
4
+ within standard ZeroGPU quota. No texture pipeline β€” mesh only.
5
+ Background removal is skipped β€” designed for clean character art.
6
+ """
7
+
8
+ import os
9
+ import tempfile
10
+
11
+ import gradio as gr
12
+ import spaces # ZeroGPU decorator
13
+ import torch
14
+ from PIL import Image
15
+
16
+ # ---------------------------------------------------------------------------
17
+ # Lazy global pipeline β€” loaded once on first GPU call
18
+ # ---------------------------------------------------------------------------
19
+ _pipeline = None
20
+
21
+
22
+ def _get_pipeline():
23
+ """Load the shape pipeline once and cache it globally."""
24
+ global _pipeline
25
+ if _pipeline is None:
26
+ from hy3dgen.shapegen import Hunyuan3DDiTFlowMatchingPipeline
27
+
28
+ _pipeline = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained(
29
+ "tencent/Hunyuan3D-2mini",
30
+ subfolder="hunyuan3d-dit-v2-mini-turbo",
31
+ use_safetensors=True,
32
+ torch_dtype=torch.float16,
33
+ )
34
+ return _pipeline
35
+
36
+
37
+ # ---------------------------------------------------------------------------
38
+ # Simple image pre-processing β€” resize only, no background removal
39
+ # ---------------------------------------------------------------------------
40
+ def preprocess_image(pil_image: Image.Image) -> Image.Image:
41
+ """Resize to 512x512 RGB β€” the model's native conditioning resolution."""
42
+ return pil_image.convert("RGB").resize((512, 512), Image.LANCZOS)
43
+
44
+
45
+ # ---------------------------------------------------------------------------
46
+ # Core generation β€” wrapped in @spaces.GPU for ZeroGPU
47
+ # ---------------------------------------------------------------------------
48
+ @spaces.GPU(duration=60)
49
+ def generate_shape(image: Image.Image, seed: int, steps: int, octree_res: int):
50
+ """
51
+ Run Hunyuan3D-DiT shape generation and return a GLB file path.
52
+
53
+ NOTE: pipeline.to("cuda") must NOT be reassigned β€” some custom pipelines
54
+ return None from .to(), which would make the pipeline uncallable.
55
+ """
56
+ pipeline = _get_pipeline()
57
+ pipeline.to("cuda") # move in-place; do not reassign the return value
58
+
59
+ generator = torch.Generator(device="cuda").manual_seed(seed)
60
+
61
+ meshes = pipeline(
62
+ image=image,
63
+ num_inference_steps=steps,
64
+ octree_resolution=octree_res,
65
+ num_chunks=8000,
66
+ generator=generator,
67
+ output_type="trimesh",
68
+ )
69
+ mesh = meshes[0]
70
+
71
+ tmp_dir = tempfile.mkdtemp()
72
+ out_path = os.path.join(tmp_dir, "shape.glb")
73
+ mesh.export(out_path)
74
+ return out_path
75
+
76
+
77
+ # ---------------------------------------------------------------------------
78
+ # Gradio UI
79
+ # ---------------------------------------------------------------------------
80
+ def run(image, seed, steps, octree_res, progress=gr.Progress(track_tqdm=True)):
81
+ if image is None:
82
+ raise gr.Error("Please upload an image first.")
83
+
84
+ progress(0.1, desc="Preprocessing image ...")
85
+ pil = image if isinstance(image, Image.Image) else Image.fromarray(image)
86
+ processed = preprocess_image(pil)
87
+
88
+ progress(0.3, desc="Running shape diffusion ...")
89
+ glb_path = generate_shape(processed, int(seed), int(steps), int(octree_res))
90
+
91
+ progress(1.0, desc="Done!")
92
+ return glb_path, processed, glb_path
93
+
94
+
95
+ with gr.Blocks(title="Hunyuan3D-2 Shape Generator", theme=gr.themes.Soft()) as demo:
96
+ gr.Markdown(
97
+ """
98
+ # Hunyuan3D-2 Shape Generator
99
+ Upload character art to generate an **untextured 3-D mesh** using
100
+ [Hunyuan3D-2mini-Turbo](https://huggingface.co/tencent/Hunyuan3D-2mini).
101
+ Shape only - no texture - stays well within the ZeroGPU free quota.
102
+ """
103
+ )
104
+
105
+ with gr.Row():
106
+ with gr.Column(scale=1):
107
+ input_image = gr.Image(
108
+ label="Input Image",
109
+ type="pil",
110
+ sources=["upload", "clipboard"],
111
+ height=340,
112
+ )
113
+
114
+ with gr.Accordion("Advanced settings", open=False):
115
+ seed = gr.Slider(
116
+ label="Seed",
117
+ minimum=0, maximum=2**31 - 1,
118
+ value=42, step=1,
119
+ )
120
+ steps = gr.Slider(
121
+ label="Diffusion steps",
122
+ minimum=5, maximum=50,
123
+ value=5, step=1,
124
+ info="5-15 works well with the turbo model.",
125
+ )
126
+ octree_res = gr.Slider(
127
+ label="Octree resolution",
128
+ minimum=128, maximum=512,
129
+ value=192, step=64,
130
+ info="Higher = finer mesh detail but more VRAM & time.",
131
+ )
132
+
133
+ generate_btn = gr.Button("Generate Shape", variant="primary")
134
+
135
+ with gr.Column(scale=1):
136
+ preview_img = gr.Image(
137
+ label="Image sent to model (512x512)",
138
+ type="pil",
139
+ interactive=False,
140
+ height=200,
141
+ )
142
+ output_3d = gr.Model3D(
143
+ label="3-D Shape (GLB)",
144
+ height=400,
145
+ clear_color=[0.9, 0.9, 0.9, 1.0],
146
+ )
147
+ download_file = gr.File(label="Download GLB")
148
+
149
+ gr.Markdown(
150
+ """
151
+ ---
152
+ **Tips**
153
+ - Works best with clean character art on a plain or transparent background.
154
+ - Lower octree resolution (128-192) is faster and still looks great for most art.
155
+ - Model: Hunyuan3D-DiT-v2-mini-Turbo - 0.6B parameters, step-distilled.
156
+ """
157
+ )
158
+
159
+ generate_btn.click(
160
+ fn=run,
161
+ inputs=[input_image, seed, steps, octree_res],
162
+ outputs=[output_3d, preview_img, download_file],
163
+ )
164
+
165
+
166
+ if __name__ == "__main__":
167
+ demo.queue(max_size=5).launch()
requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Core deps β€” torch is pre-installed by ZeroGPU; torchvision must be explicit.
2
+ # Gradio is installed by the Space runtime from sdk_version in README.md.
3
+ # Do NOT add a gradio pin here β€” it conflicts with the hardcoded Space installer command.
4
+ spaces
5
+ torchvision
6
+
7
+ # Image I/O
8
+ Pillow
9
+
10
+ # 3-D mesh I/O
11
+ trimesh
12
+ einops
13
+
14
+ # Hunyuan3D shape-generation package (no texture CUDA extensions needed)
15
+ git+https://github.com/Tencent-Hunyuan/Hunyuan3D-2.git