Huiwenshi commited on
Commit
29e1fe9
·
verified ·
1 Parent(s): 62a8c31

Upload folder using huggingface_hub

Browse files
Files changed (45) hide show
  1. .gitignore +2 -2
  2. README_zh_cn.md +16 -15
  3. assets/example_images/009.png +0 -0
  4. assets/example_images/025.png +0 -0
  5. assets/example_images/040.png +0 -0
  6. assets/example_images/045.png +0 -0
  7. assets/example_images/052.png +0 -0
  8. assets/example_images/054.png +0 -0
  9. assets/example_images/068.png +0 -0
  10. assets/example_images/073.png +0 -0
  11. assets/example_images/075.png +0 -0
  12. assets/example_images/1008.png +0 -0
  13. assets/example_images/101.png +0 -0
  14. assets/example_images/1022.png +0 -0
  15. assets/example_images/1027.png +0 -0
  16. assets/example_images/1029.png +0 -0
  17. assets/example_images/1037.png +0 -0
  18. assets/example_images/1079.png +0 -0
  19. assets/example_images/1093.png +0 -0
  20. assets/example_images/1111.png +0 -0
  21. assets/example_images/1123.png +0 -0
  22. assets/example_images/1128.png +0 -0
  23. assets/example_images/1135.png +0 -0
  24. assets/example_images/1146.png +0 -0
  25. assets/example_images/1148.png +0 -0
  26. assets/example_images/1154.png +0 -0
  27. assets/example_images/1180.png +0 -0
  28. assets/example_images/1196.png +0 -0
  29. assets/example_images/1204.png +0 -0
  30. assets/example_images/1234.png +0 -0
  31. assets/example_images/1241.png +0 -0
  32. assets/example_images/1310.png +0 -0
  33. assets/example_images/1316.png +0 -0
  34. assets/example_images/135.png +0 -0
  35. assets/example_images/1354.png +0 -0
  36. assets/example_images/1429.png +0 -0
  37. assets/example_images/1449.png +0 -0
  38. assets/example_images/1457.png +0 -0
  39. assets/images/arch.jpg +2 -2
  40. gradio_app.py +77 -89
  41. hg_app.py +416 -0
  42. hy3dgen/shapegen/pipelines.py +3 -5
  43. hy3dgen/texgen/pipelines.py +5 -7
  44. minimal_demo.py +8 -4
  45. requirements.txt +2 -0
.gitignore CHANGED
@@ -14,7 +14,7 @@ dist/
14
  downloads/
15
  eggs/
16
  .eggs/
17
- # lib/
18
  lib64/
19
  parts/
20
  sdist/
@@ -165,4 +165,4 @@ cython_debug/
165
  # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
  # and can be added to the global gitignore or merged into this file. For a more nuclear
167
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
- #.idea/
 
14
  downloads/
15
  eggs/
16
  .eggs/
17
+ lib/
18
  lib64/
19
  parts/
20
  sdist/
 
165
  # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
166
  # and can be added to the global gitignore or merged into this file. For a more nuclear
167
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
168
+ #.idea/
README_zh_cn.md CHANGED
@@ -24,12 +24,12 @@
24
 
25
  ## 概览
26
 
27
- 混元 3D 2.0 是一款先进的大规模 3D 合成系统,用于生成高分辨率的带纹理 3D
28
- 模型。该系统包含两个基础组件:一个大规模形状生成模型 —— 混元 3D-DiT,以及一个大规模纹理合成模型 —— 混元 3D-Paint。
29
- 形状生成模型构建在可扩展的基于流的扩散变换器之上,旨在生成与给定条件图像精确匹配的几何形状,为下游应用奠定坚实基础。
30
- 纹理合成模型得益于强大的几何和扩散先验知识,能够为生成的或手工制作的网格模型生成高分辨率且生动逼真的纹理贴图。
31
- 此外,我们打造了混元 3D 工作室 —— 一个功能多样、易于使用的创作平台,简化了 3D 模型的重建过程。它使专业用户和业余爱好者都能高效地对网格模型进行操作,甚至制作动画。
32
- 我们对模型进行了系统评估,结果表明混元 3D 2.0 在几何细节、条件匹配、纹理质量等方面均优于以往的先进模型,包括开源模型和闭源模型。
33
 
34
  <p align="center">
35
  <img src="assets/images/system.jpg">
@@ -39,7 +39,7 @@
39
 
40
  ### 模型架构
41
 
42
- 混元 3D 2.0 采用了两阶段生成流程,首先创建一个无纹理的网格模型,然后为该网格模型合成纹理贴图。这种策略有效地将形状生成和纹理生成的难点分离开来,同时也为生成的网格模型或手工制作的网格模型进行纹理处理提供了灵活性。
43
 
44
  <p align="left">
45
  <img src="assets/images/arch.jpg">
@@ -66,10 +66,10 @@
66
 
67
  ### 预训练模型
68
 
69
- | 模型名称 | 发布日期 | Huggingface |
70
- |----------------------|------------|-------------|
71
- | Hunyuan3D-DiT-v2-0 | 2025-01-21 | [下载]() |
72
- | Hunyuan3D-Paint-v2-0 | 2025-01-21 | [下载]() |
73
 
74
  ## 🤗快速入门 Hunyuan3D 2.0
75
 
@@ -85,7 +85,7 @@ pip install -r assets/requirements.txt
85
 
86
  ### API 使用方法
87
 
88
- 我们设计了一个类似于 diffusers 的 API 来使用我们的形状生成模型 —— 混元 3D-DiT 和纹理合成模型 —— 混元 3D-Paint。
89
  你可以通过以下方式使用 混元 3D-DiT:
90
 
91
  ```python
@@ -95,7 +95,7 @@ pipeline = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained('tencent/Hunyuan3D-2
95
  mesh = pipeline(image='assets/demo.png')[0]
96
  ```
97
 
98
- 输出的网格是一个trimesh 对象,你可以将其保存为 glb/obj(或其他格式)文件。
99
  对于 混元 3D-Paint,请执行以下操作:
100
 
101
  ```python
@@ -110,7 +110,7 @@ pipeline = Hunyuan3DPaintPipeline.from_pretrained('tencent/Hunyuan3D-2')
110
  mesh = pipeline(mesh, image='assets/demo.png')
111
  ```
112
 
113
- 请访问 minimal_demo.py 以了解更多高级用法,例如 文本转 3D 以及 为手工制作的网格生成纹理。
114
 
115
  ### Gradio App 使用方法
116
 
@@ -121,12 +121,13 @@ pip3 install gradio==3.39.0
121
  python3 gradio_app.py
122
  ```
123
 
124
- 如果你不想自己托管,别忘了访问[混元 3D]()进行快速使用。
125
 
126
  ## 📑 开源计划
127
 
128
  - [x] 推理代码
129
  - [x] 模型权重
 
130
  - [ ] ComfyUI
131
  - [ ] TensorRT 量化
132
 
 
24
 
25
  ## 概览
26
 
27
+ 混元 3D 2.0 是一款先进的大规模 3D 资产创作系统,它可以用于生成高分辨率的 3D 白膜以及带纹理的 3D
28
+ 模型。该系统包含两个基础组件:一个大规模几何生成模型 混元 3D-DiT,以及一个大规模纹理合成模型 混元 3D-Paint。
29
+ 几何生成模型基于基于流扩散的扩散模型构建,旨在生成与给定条件图像精确匹配的几何模型,为下游应用奠定坚实基础。
30
+ 纹理合成模型得益于强大的几何和扩散模型先验知识,能够为AI生成的或手工制作的网格模型生成高分辨率且生动逼真的纹理贴图。
31
+ 此外,我们打造了混元 3D 功能矩阵,一个功能多样、易于使用的创作平台,简化了 3D 模型的制作以及修改过程。它使专业用户和业余爱好者都能高效地对3D模型进行操作,甚至制作动画。
32
+ 我们对该系统进行了系统评估,结果表明混元 3D 2.0 在几何细节、条件匹配、纹理质量等方面均优于以往的最先进的开源以及闭源模型。
33
 
34
  <p align="center">
35
  <img src="assets/images/system.jpg">
 
39
 
40
  ### 模型架构
41
 
42
+ 混元 3D 2.0 采用了一个两阶段的生成过程,它首先创建一个无纹理的几何模型,然后为该几何模型合成纹理贴图。这种策略有效地将形状生成和纹理生成的难点分离开来,同时也为生成的几何模型或手工制作的几何模型进行纹理处理提供了灵活性。
43
 
44
  <p align="left">
45
  <img src="assets/images/arch.jpg">
 
66
 
67
  ### 预训练模型
68
 
69
+ | 模型名称 | 发布日期 | Huggingface |
70
+ |----------------------|------------|--------------------------------------------------|
71
+ | Hunyuan3D-DiT-v2-0 | 2025-01-21 | [下载](https://huggingface.co/tencent/Hunyuan3D-2) |
72
+ | Hunyuan3D-Paint-v2-0 | 2025-01-21 | [下载](https://huggingface.co/tencent/Hunyuan3D-2) |
73
 
74
  ## 🤗快速入门 Hunyuan3D 2.0
75
 
 
85
 
86
  ### API 使用方法
87
 
88
+ 我们设计了一个类似于 diffusers 的 API 来使用我们的几何生成模型 混元 3D-DiT 和纹理合成模型 混元 3D-Paint。
89
  你可以通过以下方式使用 混元 3D-DiT:
90
 
91
  ```python
 
95
  mesh = pipeline(image='assets/demo.png')[0]
96
  ```
97
 
98
+ 输出的网格是一个 Trimesh 对象,你可以将其保存为 glb/obj(或其他格式)文件。
99
  对于 混元 3D-Paint,请执行以下操作:
100
 
101
  ```python
 
110
  mesh = pipeline(mesh, image='assets/demo.png')
111
  ```
112
 
113
+ 请访问 [minimal_demo.py](minimal_demo.py) 以了解更多高级用法,例如 文本转 3D 以及 为手工制作的网格生成纹理。
114
 
115
  ### Gradio App 使用方法
116
 
 
121
  python3 gradio_app.py
122
  ```
123
 
124
+ 如果你不想自己托管,别忘了访问[混元 3D](https://3d.hunyuan.tencent.com)进行快速使用。
125
 
126
  ## 📑 开源计划
127
 
128
  - [x] 推理代码
129
  - [x] 模型权重
130
+ - [ ] 技术报告
131
  - [ ] ComfyUI
132
  - [ ] TensorRT 量化
133
 
assets/example_images/009.png ADDED
assets/example_images/025.png ADDED
assets/example_images/040.png ADDED
assets/example_images/045.png ADDED
assets/example_images/052.png ADDED
assets/example_images/054.png ADDED
assets/example_images/068.png ADDED
assets/example_images/073.png ADDED
assets/example_images/075.png ADDED
assets/example_images/1008.png ADDED
assets/example_images/101.png ADDED
assets/example_images/1022.png ADDED
assets/example_images/1027.png ADDED
assets/example_images/1029.png ADDED
assets/example_images/1037.png ADDED
assets/example_images/1079.png ADDED
assets/example_images/1093.png ADDED
assets/example_images/1111.png ADDED
assets/example_images/1123.png ADDED
assets/example_images/1128.png ADDED
assets/example_images/1135.png ADDED
assets/example_images/1146.png ADDED
assets/example_images/1148.png ADDED
assets/example_images/1154.png ADDED
assets/example_images/1180.png ADDED
assets/example_images/1196.png ADDED
assets/example_images/1204.png ADDED
assets/example_images/1234.png ADDED
assets/example_images/1241.png ADDED
assets/example_images/1310.png ADDED
assets/example_images/1316.png ADDED
assets/example_images/135.png ADDED
assets/example_images/1354.png ADDED
assets/example_images/1429.png ADDED
assets/example_images/1449.png ADDED
assets/example_images/1457.png CHANGED
assets/images/arch.jpg CHANGED

Git LFS Details

  • SHA256: 409049cd3ba0c477d4ef85e82b03fb7d642cecabe8a44c5824818a435ed166d1
  • Pointer size: 132 Bytes
  • Size of remote file: 1.18 MB

Git LFS Details

  • SHA256: 7ac9e63cbe30dd141832ed1c949d23a7186c5681073fa8d173ee9c1f5f81a18e
  • Pointer size: 131 Bytes
  • Size of remote file: 903 kB
gradio_app.py CHANGED
@@ -1,36 +1,15 @@
1
- # pip install gradio==3.39.0
2
  import os
3
- import subprocess
4
- def install_cuda_toolkit():
5
- # CUDA_TOOLKIT_URL = "https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run"
6
- CUDA_TOOLKIT_URL = "https://developer.download.nvidia.com/compute/cuda/12.2.0/local_installers/cuda_12.2.0_535.54.03_linux.run"
7
- CUDA_TOOLKIT_FILE = "/tmp/%s" % os.path.basename(CUDA_TOOLKIT_URL)
8
- subprocess.call(["wget", "-q", CUDA_TOOLKIT_URL, "-O", CUDA_TOOLKIT_FILE])
9
- subprocess.call(["chmod", "+x", CUDA_TOOLKIT_FILE])
10
- subprocess.call([CUDA_TOOLKIT_FILE, "--silent", "--toolkit"])
11
-
12
- os.environ["CUDA_HOME"] = "/usr/local/cuda"
13
- os.environ["PATH"] = "%s/bin:%s" % (os.environ["CUDA_HOME"], os.environ["PATH"])
14
- os.environ["LD_LIBRARY_PATH"] = "%s/lib:%s" % (
15
- os.environ["CUDA_HOME"],
16
- "" if "LD_LIBRARY_PATH" not in os.environ else os.environ["LD_LIBRARY_PATH"],
17
- )
18
- # Fix: arch_list[-1] += '+PTX'; IndexError: list index out of range
19
- os.environ["TORCH_CUDA_ARCH_LIST"] = "8.0;8.6"
20
-
21
- install_cuda_toolkit()
22
- os.system("cd /home/user/app/hy3dgen/texgen/differentiable_renderer/ && bash compile_mesh_painter.sh")
23
- os.system("cd /home/user/app/hy3dgen/texgen/custom_rasterizer && pip install .")
24
- # os.system("cd /home/user/app/hy3dgen/texgen/custom_rasterizer && CUDA_HOME=/usr/local/cuda FORCE_CUDA=1 TORCH_CUDA_ARCH_LIST='8.0;8.6;8.9;9.0' python setup.py install")
25
-
26
  import shutil
27
  import time
28
  from glob import glob
 
 
29
  import gradio as gr
30
  import torch
31
- from gradio_litmodel3d import LitModel3D
 
 
32
 
33
- import spaces
34
 
35
  def get_example_img_list():
36
  print('Loading example img list ...')
@@ -92,7 +71,8 @@ def build_model_viewer_html(save_folder, height=660, width=790, textured=False):
92
  with open(output_html_path, 'w') as f:
93
  f.write(template_html.replace('<model-viewer>', obj_html))
94
 
95
- iframe_tag = f'<iframe src="file/{output_html_path}" height="{height}" width="100%" frameborder="0"></iframe>'
 
96
  print(f'Find html {output_html_path}, {os.path.exists(output_html_path)}')
97
 
98
  return f"""
@@ -101,7 +81,7 @@ def build_model_viewer_html(save_folder, height=660, width=790, textured=False):
101
  </div>
102
  """
103
 
104
- @spaces.GPU(duration=60)
105
  def _gen_shape(
106
  caption,
107
  image,
@@ -117,10 +97,12 @@ def _gen_shape(
117
  time_meta = {}
118
  start_time_0 = time.time()
119
 
120
- image_path = ''
121
  if image is None:
122
  start_time = time.time()
123
- image = t2i_worker(caption)
 
 
 
124
  time_meta['text2image'] = time.time() - start_time
125
 
126
  image.save(os.path.join(save_folder, 'input.png'))
@@ -158,7 +140,7 @@ def _gen_shape(
158
  stats['time'] = time_meta
159
  return mesh, save_folder
160
 
161
- @spaces.GPU(duration=80)
162
  def generation_all(
163
  caption,
164
  image,
@@ -187,13 +169,11 @@ def generation_all(
187
  return (
188
  gr.update(value=path, visible=True),
189
  gr.update(value=path_textured, visible=True),
190
- gr.update(value=path, visible=True),
191
- gr.update(value=path_textured, visible=True),
192
- # model_viewer_html,
193
- # model_viewer_html_textured,
194
  )
195
 
196
- @spaces.GPU(duration=30)
197
  def shape_generation(
198
  caption,
199
  image,
@@ -218,39 +198,28 @@ def shape_generation(
218
 
219
  return (
220
  gr.update(value=path, visible=True),
221
- gr.update(value=path, visible=True),
222
- # model_viewer_html,
223
  )
224
 
225
 
226
  def build_app():
227
  title_html = """
228
- <div style="font-size: 2em; font-weight: bold; text-align: center; margin-bottom: 20px">
229
-
230
  Hunyuan3D-2: Scaling Diffusion Models for High Resolution Textured 3D Assets Generation
231
  </div>
232
  <div align="center">
233
  Tencent Hunyuan3D Team
234
  </div>
235
  <div align="center">
236
- <a href="https://github.com/tencent/Hunyuan3D-1">Github Page</a> &ensp;
237
  <a href="http://3d-models.hunyuan.tencent.com">Homepage</a> &ensp;
238
- <a href="https://arxiv.org/pdf/2411.02293">Technical Report</a> &ensp;
239
  <a href="https://huggingface.co/Tencent/Hunyuan3D-2"> Models</a> &ensp;
240
  </div>
241
  """
242
- css = """
243
- .json-output {
244
- height: 578px;
245
- }
246
- .json-output .json-holder {
247
- height: 538px;
248
- overflow-y: scroll;
249
- }
250
- """
251
 
252
- with gr.Blocks(theme=gr.themes.Base(), css=css, title='Hunyuan-3D-2.0') as demo:
253
- # if not gr.__version__.startswith('4'): gr.HTML(title_html)
254
  gr.HTML(title_html)
255
 
256
  with gr.Row():
@@ -261,7 +230,7 @@ def build_app():
261
  with gr.Row():
262
  check_box_rembg = gr.Checkbox(value=True, label='Remove Background')
263
 
264
- with gr.Tab('Text Prompt', id='tab_txt_prompt') as tab_tp:
265
  caption = gr.Textbox(label='Text Prompt',
266
  placeholder='HunyuanDiT will be used to generate image.',
267
  info='Example: A 3D model of a cute cat, white background')
@@ -274,7 +243,7 @@ def build_app():
274
 
275
  with gr.Group():
276
  btn = gr.Button(value='Generate Shape Only', variant='primary')
277
- btn_all = gr.Button(value='Generate Shape and Texture', variant='primary')
278
 
279
  with gr.Group():
280
  file_out = gr.File(label="File", visible=False)
@@ -283,29 +252,9 @@ def build_app():
283
  with gr.Column(scale=5):
284
  with gr.Tabs():
285
  with gr.Tab('Generated Mesh') as mesh1:
286
- mesh_output1 = LitModel3D(
287
- label="3D Model1",
288
- exposure=10.0,
289
- height=600,
290
- visible=True,
291
- clear_color=[0.0, 0.0, 0.0, 0.0],
292
- tonemapping="aces",
293
- contrast=1.0,
294
- scale=1.0,
295
- )
296
- # html_output1 = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
297
  with gr.Tab('Generated Textured Mesh') as mesh2:
298
- # html_output2 = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
299
- mesh_output2 = LitModel3D(
300
- label="3D Model2",
301
- exposure=10.0,
302
- height=600,
303
- visible=True,
304
- clear_color=[0.0, 0.0, 0.0, 0.0],
305
- tonemapping="aces",
306
- contrast=1.0,
307
- scale=1.0,
308
- )
309
 
310
  with gr.Column(scale=2):
311
  with gr.Tabs() as gallery:
@@ -314,13 +263,30 @@ def build_app():
314
  gr.Examples(examples=example_is, inputs=[image],
315
  label="Image Prompts", examples_per_page=18)
316
 
317
- with gr.Tab('Text to 3D Gallery', id='tab_txt_gallery') as tab_gt:
318
  with gr.Row():
319
  gr.Examples(examples=example_ts, inputs=[caption],
320
  label="Text Prompts", examples_per_page=18)
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  tab_gi.select(fn=lambda: gr.update(selected='tab_img_prompt'), outputs=tabs_prompt)
323
- tab_gt.select(fn=lambda: gr.update(selected='tab_txt_prompt'), outputs=tabs_prompt)
 
324
 
325
  btn.click(
326
  shape_generation,
@@ -333,8 +299,7 @@ def build_app():
333
  octree_resolution,
334
  check_box_rembg,
335
  ],
336
- # outputs=[file_out, html_output1]
337
- outputs=[file_out, mesh_output1]
338
  ).then(
339
  lambda: gr.update(visible=True),
340
  outputs=[file_out],
@@ -351,8 +316,7 @@ def build_app():
351
  octree_resolution,
352
  check_box_rembg,
353
  ],
354
- # outputs=[file_out, file_out2, html_output1, html_output2]
355
- outputs=[file_out, file_out2, mesh_output1, mesh_output2]
356
  ).then(
357
  lambda: (gr.update(visible=True), gr.update(visible=True)),
358
  outputs=[file_out, file_out2],
@@ -366,7 +330,8 @@ if __name__ == '__main__':
366
 
367
  parser = argparse.ArgumentParser()
368
  parser.add_argument('--port', type=int, default=8080)
369
- parser.add_argument('--cache-path', type=str, default='./gradio_cache')
 
370
  args = parser.parse_args()
371
 
372
  SAVE_DIR = args.cache_path
@@ -386,19 +351,42 @@ if __name__ == '__main__':
386
  example_is = get_example_img_list()
387
  example_ts = get_example_txt_list()
388
 
389
- from hy3dgen.text2image import HunyuanDiTPipeline
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  from hy3dgen.shapegen import FaceReducer, FloaterRemover, DegenerateFaceRemover, \
391
  Hunyuan3DDiTFlowMatchingPipeline
392
- from hy3dgen.texgen import Hunyuan3DPaintPipeline
393
  from hy3dgen.rembg import BackgroundRemover
394
 
395
  rmbg_worker = BackgroundRemover()
396
- t2i_worker = HunyuanDiTPipeline()
397
  i23d_worker = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained('tencent/Hunyuan3D-2')
398
- texgen_worker = Hunyuan3DPaintPipeline.from_pretrained('tencent/Hunyuan3D-2')
399
  floater_remove_worker = FloaterRemover()
400
  degenerate_face_remove_worker = DegenerateFaceRemover()
401
  face_reduce_worker = FaceReducer()
402
 
 
 
 
 
 
 
 
 
403
  demo = build_app()
404
- demo.queue().launch()
 
 
 
1
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import shutil
3
  import time
4
  from glob import glob
5
+ from pathlib import Path
6
+
7
  import gradio as gr
8
  import torch
9
+ import uvicorn
10
+ from fastapi import FastAPI
11
+ from fastapi.staticfiles import StaticFiles
12
 
 
13
 
14
  def get_example_img_list():
15
  print('Loading example img list ...')
 
71
  with open(output_html_path, 'w') as f:
72
  f.write(template_html.replace('<model-viewer>', obj_html))
73
 
74
+ output_html_path = output_html_path.replace(SAVE_DIR + '/', '')
75
+ iframe_tag = f'<iframe src="/static/{output_html_path}" height="{height}" width="100%" frameborder="0"></iframe>'
76
  print(f'Find html {output_html_path}, {os.path.exists(output_html_path)}')
77
 
78
  return f"""
 
81
  </div>
82
  """
83
 
84
+
85
  def _gen_shape(
86
  caption,
87
  image,
 
97
  time_meta = {}
98
  start_time_0 = time.time()
99
 
 
100
  if image is None:
101
  start_time = time.time()
102
+ try:
103
+ image = t2i_worker(caption)
104
+ except Exception as e:
105
+ raise gr.Error(f"Text to 3D is disable. Please enable it by `python gradio_app.py --enable_t23d`.")
106
  time_meta['text2image'] = time.time() - start_time
107
 
108
  image.save(os.path.join(save_folder, 'input.png'))
 
140
  stats['time'] = time_meta
141
  return mesh, save_folder
142
 
143
+
144
  def generation_all(
145
  caption,
146
  image,
 
169
  return (
170
  gr.update(value=path, visible=True),
171
  gr.update(value=path_textured, visible=True),
172
+ model_viewer_html,
173
+ model_viewer_html_textured,
 
 
174
  )
175
 
176
+
177
  def shape_generation(
178
  caption,
179
  image,
 
198
 
199
  return (
200
  gr.update(value=path, visible=True),
201
+ model_viewer_html,
 
202
  )
203
 
204
 
205
  def build_app():
206
  title_html = """
207
+ <div style="font-size: 2em; font-weight: bold; text-align: center; margin-bottom: 5px">
208
+
209
  Hunyuan3D-2: Scaling Diffusion Models for High Resolution Textured 3D Assets Generation
210
  </div>
211
  <div align="center">
212
  Tencent Hunyuan3D Team
213
  </div>
214
  <div align="center">
215
+ <a href="https://github.com/tencent/Hunyuan3D-2">Github Page</a> &ensp;
216
  <a href="http://3d-models.hunyuan.tencent.com">Homepage</a> &ensp;
217
+ <a href="#">Technical Report</a> &ensp;
218
  <a href="https://huggingface.co/Tencent/Hunyuan3D-2"> Models</a> &ensp;
219
  </div>
220
  """
 
 
 
 
 
 
 
 
 
221
 
222
+ with gr.Blocks(theme=gr.themes.Base(), title='Hunyuan-3D-2.0') as demo:
 
223
  gr.HTML(title_html)
224
 
225
  with gr.Row():
 
230
  with gr.Row():
231
  check_box_rembg = gr.Checkbox(value=True, label='Remove Background')
232
 
233
+ with gr.Tab('Text Prompt', id='tab_txt_prompt', visible=HAS_T2I) as tab_tp:
234
  caption = gr.Textbox(label='Text Prompt',
235
  placeholder='HunyuanDiT will be used to generate image.',
236
  info='Example: A 3D model of a cute cat, white background')
 
243
 
244
  with gr.Group():
245
  btn = gr.Button(value='Generate Shape Only', variant='primary')
246
+ btn_all = gr.Button(value='Generate Shape and Texture', variant='primary', visible=HAS_TEXTUREGEN)
247
 
248
  with gr.Group():
249
  file_out = gr.File(label="File", visible=False)
 
252
  with gr.Column(scale=5):
253
  with gr.Tabs():
254
  with gr.Tab('Generated Mesh') as mesh1:
255
+ html_output1 = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
 
 
 
 
 
 
 
 
 
 
256
  with gr.Tab('Generated Textured Mesh') as mesh2:
257
+ html_output2 = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
 
 
 
 
 
 
 
 
 
 
258
 
259
  with gr.Column(scale=2):
260
  with gr.Tabs() as gallery:
 
263
  gr.Examples(examples=example_is, inputs=[image],
264
  label="Image Prompts", examples_per_page=18)
265
 
266
+ with gr.Tab('Text to 3D Gallery', id='tab_txt_gallery', visible=HAS_T2I) as tab_gt:
267
  with gr.Row():
268
  gr.Examples(examples=example_ts, inputs=[caption],
269
  label="Text Prompts", examples_per_page=18)
270
 
271
+ if not HAS_TEXTUREGEN:
272
+ gr.HTML(""")
273
+ <div style="margin-top: 20px;">
274
+ <b>Warning: </b>
275
+ Texture synthesis is disable due to missing requirements,
276
+ please install requirements following README.md to activate it.
277
+ </div>
278
+ """)
279
+ if not args.enable_t23d:
280
+ gr.HTML("""
281
+ <div style="margin-top: 20px;">
282
+ <b>Warning: </b>
283
+ Text to 3D is disable. To activate it, please run `python gradio_app.py --enable_t23d`.
284
+ </div>
285
+ """)
286
+
287
  tab_gi.select(fn=lambda: gr.update(selected='tab_img_prompt'), outputs=tabs_prompt)
288
+ if HAS_T2I:
289
+ tab_gt.select(fn=lambda: gr.update(selected='tab_txt_prompt'), outputs=tabs_prompt)
290
 
291
  btn.click(
292
  shape_generation,
 
299
  octree_resolution,
300
  check_box_rembg,
301
  ],
302
+ outputs=[file_out, html_output1]
 
303
  ).then(
304
  lambda: gr.update(visible=True),
305
  outputs=[file_out],
 
316
  octree_resolution,
317
  check_box_rembg,
318
  ],
319
+ outputs=[file_out, file_out2, html_output1, html_output2]
 
320
  ).then(
321
  lambda: (gr.update(visible=True), gr.update(visible=True)),
322
  outputs=[file_out, file_out2],
 
330
 
331
  parser = argparse.ArgumentParser()
332
  parser.add_argument('--port', type=int, default=8080)
333
+ parser.add_argument('--cache-path', type=str, default='gradio_cache')
334
+ parser.add_argument('--enable_t23d', action='store_true')
335
  args = parser.parse_args()
336
 
337
  SAVE_DIR = args.cache_path
 
351
  example_is = get_example_img_list()
352
  example_ts = get_example_txt_list()
353
 
354
+ try:
355
+ from hy3dgen.texgen import Hunyuan3DPaintPipeline
356
+
357
+ texgen_worker = Hunyuan3DPaintPipeline.from_pretrained('tencent/Hunyuan3D-2')
358
+ HAS_TEXTUREGEN = True
359
+ except Exception as e:
360
+ print(e)
361
+ print("Failed to load texture generator.")
362
+ print('Please try to install requirements by following README.md')
363
+ HAS_TEXTUREGEN = False
364
+
365
+ HAS_T2I = False
366
+ if args.enable_t23d:
367
+ from hy3dgen.text2image import HunyuanDiTPipeline
368
+
369
+ t2i_worker = HunyuanDiTPipeline('Tencent-Hunyuan/HunyuanDiT-v1.1-Diffusers-Distilled')
370
+ HAS_T2I = True
371
+
372
  from hy3dgen.shapegen import FaceReducer, FloaterRemover, DegenerateFaceRemover, \
373
  Hunyuan3DDiTFlowMatchingPipeline
 
374
  from hy3dgen.rembg import BackgroundRemover
375
 
376
  rmbg_worker = BackgroundRemover()
 
377
  i23d_worker = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained('tencent/Hunyuan3D-2')
 
378
  floater_remove_worker = FloaterRemover()
379
  degenerate_face_remove_worker = DegenerateFaceRemover()
380
  face_reduce_worker = FaceReducer()
381
 
382
+ # https://discuss.huggingface.co/t/how-to-serve-an-html-file/33921/2
383
+ # create a FastAPI app
384
+ app = FastAPI()
385
+ # create a static directory to store the static files
386
+ static_dir = Path('./gradio_cache')
387
+ static_dir.mkdir(parents=True, exist_ok=True)
388
+ app.mount("/static", StaticFiles(directory=static_dir), name="static")
389
+
390
  demo = build_app()
391
+ app = gr.mount_gradio_app(app, demo, path="/")
392
+ uvicorn.run(app, host="0.0.0.0", port=args.port)
hg_app.py ADDED
@@ -0,0 +1,416 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import spaces
3
+ import subprocess
4
+ def install_cuda_toolkit():
5
+ # CUDA_TOOLKIT_URL = "https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda_11.8.0_520.61.05_linux.run"
6
+ CUDA_TOOLKIT_URL = "https://developer.download.nvidia.com/compute/cuda/12.2.0/local_installers/cuda_12.2.0_535.54.03_linux.run"
7
+ CUDA_TOOLKIT_FILE = "/tmp/%s" % os.path.basename(CUDA_TOOLKIT_URL)
8
+ subprocess.call(["wget", "-q", CUDA_TOOLKIT_URL, "-O", CUDA_TOOLKIT_FILE])
9
+ subprocess.call(["chmod", "+x", CUDA_TOOLKIT_FILE])
10
+ subprocess.call([CUDA_TOOLKIT_FILE, "--silent", "--toolkit"])
11
+
12
+ os.environ["CUDA_HOME"] = "/usr/local/cuda"
13
+ os.environ["PATH"] = "%s/bin:%s" % (os.environ["CUDA_HOME"], os.environ["PATH"])
14
+ os.environ["LD_LIBRARY_PATH"] = "%s/lib:%s" % (
15
+ os.environ["CUDA_HOME"],
16
+ "" if "LD_LIBRARY_PATH" not in os.environ else os.environ["LD_LIBRARY_PATH"],
17
+ )
18
+ # Fix: arch_list[-1] += '+PTX'; IndexError: list index out of range
19
+ os.environ["TORCH_CUDA_ARCH_LIST"] = "8.0;8.6"
20
+
21
+ install_cuda_toolkit()
22
+ os.system("cd /home/user/app/hy3dgen/texgen/differentiable_renderer/ && bash compile_mesh_painter.sh")
23
+ os.system("cd /home/user/app/hy3dgen/texgen/custom_rasterizer && pip install .")
24
+
25
+ import os
26
+ import shutil
27
+ import time
28
+ from glob import glob
29
+ from pathlib import Path
30
+
31
+ import gradio as gr
32
+ import torch
33
+ import uvicorn
34
+ from fastapi import FastAPI
35
+ from fastapi.staticfiles import StaticFiles
36
+
37
+
38
+ def get_example_img_list():
39
+ print('Loading example img list ...')
40
+ return sorted(glob('./assets/example_images/*.png'))
41
+
42
+
43
+ def get_example_txt_list():
44
+ print('Loading example txt list ...')
45
+ txt_list = list()
46
+ for line in open('./assets/example_prompts.txt'):
47
+ txt_list.append(line.strip())
48
+ return txt_list
49
+
50
+
51
+ def gen_save_folder(max_size=60):
52
+ os.makedirs(SAVE_DIR, exist_ok=True)
53
+ exists = set(int(_) for _ in os.listdir(SAVE_DIR) if not _.startswith("."))
54
+ cur_id = min(set(range(max_size)) - exists) if len(exists) < max_size else -1
55
+ if os.path.exists(f"{SAVE_DIR}/{(cur_id + 1) % max_size}"):
56
+ shutil.rmtree(f"{SAVE_DIR}/{(cur_id + 1) % max_size}")
57
+ print(f"remove {SAVE_DIR}/{(cur_id + 1) % max_size} success !!!")
58
+ save_folder = f"{SAVE_DIR}/{max(0, cur_id)}"
59
+ os.makedirs(save_folder, exist_ok=True)
60
+ print(f"mkdir {save_folder} suceess !!!")
61
+ return save_folder
62
+
63
+
64
+ def export_mesh(mesh, save_folder, textured=False):
65
+ if textured:
66
+ path = os.path.join(save_folder, f'textured_mesh.glb')
67
+ else:
68
+ path = os.path.join(save_folder, f'white_mesh.glb')
69
+ mesh.export(path, include_normals=textured)
70
+ return path
71
+
72
+
73
+ def build_model_viewer_html(save_folder, height=660, width=790, textured=False):
74
+ if textured:
75
+ related_path = f"./textured_mesh.glb"
76
+ template_name = './assets/modelviewer-textured-template.html'
77
+ output_html_path = os.path.join(save_folder, f'textured_mesh.html')
78
+ else:
79
+ related_path = f"./white_mesh.glb"
80
+ template_name = './assets/modelviewer-template.html'
81
+ output_html_path = os.path.join(save_folder, f'white_mesh.html')
82
+
83
+ with open(os.path.join(CURRENT_DIR, template_name), 'r') as f:
84
+ template_html = f.read()
85
+ obj_html = f"""
86
+ <div class="column is-mobile is-centered">
87
+ <model-viewer style="height: {height - 10}px; width: {width}px;" rotation-per-second="10deg" id="modelViewer"
88
+ src="{related_path}/" disable-tap
89
+ environment-image="neutral" auto-rotate camera-target="0m 0m 0m" orientation="0deg 0deg 170deg" shadow-intensity=".9"
90
+ ar auto-rotate camera-controls>
91
+ </model-viewer>
92
+ </div>
93
+ """
94
+
95
+ with open(output_html_path, 'w') as f:
96
+ f.write(template_html.replace('<model-viewer>', obj_html))
97
+
98
+ output_html_path = output_html_path.replace(SAVE_DIR + '/', '')
99
+ iframe_tag = f'<iframe src="/static/{output_html_path}" height="{height}" width="100%" frameborder="0"></iframe>'
100
+ print(f'Find html {output_html_path}, {os.path.exists(output_html_path)}')
101
+
102
+ return f"""
103
+ <div style='height: {height}; width: 100%;'>
104
+ {iframe_tag}
105
+ </div>
106
+ """
107
+
108
+ @spaces.GPU(duration=40)
109
+ def _gen_shape(
110
+ caption,
111
+ image,
112
+ steps=50,
113
+ guidance_scale=7.5,
114
+ seed=1234,
115
+ octree_resolution=256,
116
+ check_box_rembg=False,
117
+ ):
118
+ if caption: print('prompt is', caption)
119
+ save_folder = gen_save_folder()
120
+ stats = {}
121
+ time_meta = {}
122
+ start_time_0 = time.time()
123
+
124
+ if image is None:
125
+ start_time = time.time()
126
+ try:
127
+ image = t2i_worker(caption)
128
+ except Exception as e:
129
+ raise gr.Error(f"Text to 3D is disable. Please enable it by `python gradio_app.py --enable_t23d`.")
130
+ time_meta['text2image'] = time.time() - start_time
131
+
132
+ image.save(os.path.join(save_folder, 'input.png'))
133
+
134
+ print(image.mode)
135
+ if check_box_rembg or image.mode == "RGB":
136
+ start_time = time.time()
137
+ image = rmbg_worker(image.convert('RGB'))
138
+ time_meta['rembg'] = time.time() - start_time
139
+
140
+ image.save(os.path.join(save_folder, 'rembg.png'))
141
+
142
+ # image to white model
143
+ start_time = time.time()
144
+
145
+ generator = torch.Generator()
146
+ generator = generator.manual_seed(int(seed))
147
+ mesh = i23d_worker(
148
+ image=image,
149
+ num_inference_steps=steps,
150
+ guidance_scale=guidance_scale,
151
+ generator=generator,
152
+ octree_resolution=octree_resolution
153
+ )[0]
154
+
155
+ mesh = FloaterRemover()(mesh)
156
+ mesh = DegenerateFaceRemover()(mesh)
157
+ mesh = FaceReducer()(mesh)
158
+
159
+ stats['number_of_faces'] = mesh.faces.shape[0]
160
+ stats['number_of_vertices'] = mesh.vertices.shape[0]
161
+
162
+ time_meta['image_to_textured_3d'] = {'total': time.time() - start_time}
163
+ time_meta['total'] = time.time() - start_time_0
164
+ stats['time'] = time_meta
165
+ return mesh, save_folder
166
+
167
+ @spaces.GPU(duration=60)
168
+ def generation_all(
169
+ caption,
170
+ image,
171
+ steps=50,
172
+ guidance_scale=7.5,
173
+ seed=1234,
174
+ octree_resolution=256,
175
+ check_box_rembg=False
176
+ ):
177
+ mesh, save_folder = _gen_shape(
178
+ caption,
179
+ image,
180
+ steps=steps,
181
+ guidance_scale=guidance_scale,
182
+ seed=seed,
183
+ octree_resolution=octree_resolution,
184
+ check_box_rembg=check_box_rembg
185
+ )
186
+ path = export_mesh(mesh, save_folder, textured=False)
187
+ model_viewer_html = build_model_viewer_html(save_folder, height=596, width=700)
188
+
189
+ textured_mesh = texgen_worker(mesh, image)
190
+ path_textured = export_mesh(textured_mesh, save_folder, textured=True)
191
+ model_viewer_html_textured = build_model_viewer_html(save_folder, height=596, width=700, textured=True)
192
+
193
+ return (
194
+ gr.update(value=path, visible=True),
195
+ gr.update(value=path_textured, visible=True),
196
+ model_viewer_html,
197
+ model_viewer_html_textured,
198
+ )
199
+
200
+ @spaces.GPU(duration=40)
201
+ def shape_generation(
202
+ caption,
203
+ image,
204
+ steps=50,
205
+ guidance_scale=7.5,
206
+ seed=1234,
207
+ octree_resolution=256,
208
+ check_box_rembg=False,
209
+ ):
210
+ mesh, save_folder = _gen_shape(
211
+ caption,
212
+ image,
213
+ steps=steps,
214
+ guidance_scale=guidance_scale,
215
+ seed=seed,
216
+ octree_resolution=octree_resolution,
217
+ check_box_rembg=check_box_rembg
218
+ )
219
+
220
+ path = export_mesh(mesh, save_folder, textured=False)
221
+ model_viewer_html = build_model_viewer_html(save_folder, height=596, width=700)
222
+
223
+ return (
224
+ gr.update(value=path, visible=True),
225
+ model_viewer_html,
226
+ )
227
+
228
+
229
+ def build_app():
230
+ title_html = """
231
+ <div style="font-size: 2em; font-weight: bold; text-align: center; margin-bottom: 5px">
232
+
233
+ Hunyuan3D-2: Scaling Diffusion Models for High Resolution Textured 3D Assets Generation
234
+ </div>
235
+ <div align="center">
236
+ Tencent Hunyuan3D Team
237
+ </div>
238
+ <div align="center">
239
+ <a href="https://github.com/tencent/Hunyuan3D-2">Github Page</a> &ensp;
240
+ <a href="http://3d-models.hunyuan.tencent.com">Homepage</a> &ensp;
241
+ <a href="#">Technical Report</a> &ensp;
242
+ <a href="https://huggingface.co/Tencent/Hunyuan3D-2"> Models</a> &ensp;
243
+ </div>
244
+ """
245
+
246
+ with gr.Blocks(theme=gr.themes.Base(), title='Hunyuan-3D-2.0') as demo:
247
+ gr.HTML(title_html)
248
+
249
+ with gr.Row():
250
+ with gr.Column(scale=2):
251
+ with gr.Tabs() as tabs_prompt:
252
+ with gr.Tab('Image Prompt', id='tab_img_prompt') as tab_ip:
253
+ image = gr.Image(label='Image', type='pil', image_mode='RGBA', height=290)
254
+ with gr.Row():
255
+ check_box_rembg = gr.Checkbox(value=True, label='Remove Background')
256
+
257
+ with gr.Tab('Text Prompt', id='tab_txt_prompt', visible=HAS_T2I) as tab_tp:
258
+ caption = gr.Textbox(label='Text Prompt',
259
+ placeholder='HunyuanDiT will be used to generate image.',
260
+ info='Example: A 3D model of a cute cat, white background')
261
+
262
+ with gr.Accordion('Advanced Options', open=False):
263
+ num_steps = gr.Slider(maximum=50, minimum=20, value=30, step=1, label='Inference Steps')
264
+ octree_resolution = gr.Dropdown([256, 384, 512], value=256, label='Octree Resolution')
265
+ cfg_scale = gr.Number(value=5.5, label='Guidance Scale')
266
+ seed = gr.Slider(maximum=1e7, minimum=0, value=1234, label='Seed')
267
+
268
+ with gr.Group():
269
+ btn = gr.Button(value='Generate Shape Only', variant='primary')
270
+ btn_all = gr.Button(value='Generate Shape and Texture', variant='primary', visible=HAS_TEXTUREGEN)
271
+
272
+ with gr.Group():
273
+ file_out = gr.File(label="File", visible=False)
274
+ file_out2 = gr.File(label="File", visible=False)
275
+
276
+ with gr.Column(scale=5):
277
+ with gr.Tabs():
278
+ with gr.Tab('Generated Mesh') as mesh1:
279
+ html_output1 = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
280
+ with gr.Tab('Generated Textured Mesh') as mesh2:
281
+ html_output2 = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
282
+
283
+ with gr.Column(scale=2):
284
+ with gr.Tabs() as gallery:
285
+ with gr.Tab('Image to 3D Gallery', id='tab_img_gallery') as tab_gi:
286
+ with gr.Row():
287
+ gr.Examples(examples=example_is, inputs=[image],
288
+ label="Image Prompts", examples_per_page=18)
289
+
290
+ with gr.Tab('Text to 3D Gallery', id='tab_txt_gallery', visible=HAS_T2I) as tab_gt:
291
+ with gr.Row():
292
+ gr.Examples(examples=example_ts, inputs=[caption],
293
+ label="Text Prompts", examples_per_page=18)
294
+
295
+ if not HAS_TEXTUREGEN:
296
+ gr.HTML(""")
297
+ <div style="margin-top: 20px;">
298
+ <b>Warning: </b>
299
+ Texture synthesis is disable due to missing requirements,
300
+ please install requirements following README.md to activate it.
301
+ </div>
302
+ """)
303
+ if not args.enable_t23d:
304
+ gr.HTML("""
305
+ <div style="margin-top: 20px;">
306
+ <b>Warning: </b>
307
+ Text to 3D is disable. To activate it, please run `python gradio_app.py --enable_t23d`.
308
+ </div>
309
+ """)
310
+
311
+ tab_gi.select(fn=lambda: gr.update(selected='tab_img_prompt'), outputs=tabs_prompt)
312
+ if HAS_T2I:
313
+ tab_gt.select(fn=lambda: gr.update(selected='tab_txt_prompt'), outputs=tabs_prompt)
314
+
315
+ btn.click(
316
+ shape_generation,
317
+ inputs=[
318
+ caption,
319
+ image,
320
+ num_steps,
321
+ cfg_scale,
322
+ seed,
323
+ octree_resolution,
324
+ check_box_rembg,
325
+ ],
326
+ outputs=[file_out, html_output1]
327
+ ).then(
328
+ lambda: gr.update(visible=True),
329
+ outputs=[file_out],
330
+ )
331
+
332
+ btn_all.click(
333
+ generation_all,
334
+ inputs=[
335
+ caption,
336
+ image,
337
+ num_steps,
338
+ cfg_scale,
339
+ seed,
340
+ octree_resolution,
341
+ check_box_rembg,
342
+ ],
343
+ outputs=[file_out, file_out2, html_output1, html_output2]
344
+ ).then(
345
+ lambda: (gr.update(visible=True), gr.update(visible=True)),
346
+ outputs=[file_out, file_out2],
347
+ )
348
+
349
+ return demo
350
+
351
+
352
+ if __name__ == '__main__':
353
+ import argparse
354
+
355
+ parser = argparse.ArgumentParser()
356
+ parser.add_argument('--port', type=int, default=8080)
357
+ parser.add_argument('--cache-path', type=str, default='gradio_cache')
358
+ parser.add_argument('--enable_t23d', default=True)
359
+ args = parser.parse_args()
360
+
361
+ SAVE_DIR = args.cache_path
362
+ os.makedirs(SAVE_DIR, exist_ok=True)
363
+
364
+ CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
365
+
366
+ HTML_OUTPUT_PLACEHOLDER = """
367
+ <div style='height: 596px; width: 100%; border-radius: 8px; border-color: #e5e7eb; order-style: solid; border-width: 1px;'></div>
368
+ """
369
+
370
+ INPUT_MESH_HTML = """
371
+ <div style='height: 490px; width: 100%; border-radius: 8px;
372
+ border-color: #e5e7eb; order-style: solid; border-width: 1px;'>
373
+ </div>
374
+ """
375
+ example_is = get_example_img_list()
376
+ example_ts = get_example_txt_list()
377
+
378
+ try:
379
+ from hy3dgen.texgen import Hunyuan3DPaintPipeline
380
+
381
+ texgen_worker = Hunyuan3DPaintPipeline.from_pretrained('tencent/Hunyuan3D-2')
382
+ HAS_TEXTUREGEN = True
383
+ except Exception as e:
384
+ print(e)
385
+ print("Failed to load texture generator.")
386
+ print('Please try to install requirements by following README.md')
387
+ HAS_TEXTUREGEN = False
388
+
389
+ HAS_T2I = False
390
+ if args.enable_t23d:
391
+ from hy3dgen.text2image import HunyuanDiTPipeline
392
+
393
+ t2i_worker = HunyuanDiTPipeline('Tencent-Hunyuan/HunyuanDiT-v1.1-Diffusers-Distilled')
394
+ HAS_T2I = True
395
+
396
+ from hy3dgen.shapegen import FaceReducer, FloaterRemover, DegenerateFaceRemover, \
397
+ Hunyuan3DDiTFlowMatchingPipeline
398
+ from hy3dgen.rembg import BackgroundRemover
399
+
400
+ rmbg_worker = BackgroundRemover()
401
+ i23d_worker = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained('tencent/Hunyuan3D-2')
402
+ floater_remove_worker = FloaterRemover()
403
+ degenerate_face_remove_worker = DegenerateFaceRemover()
404
+ face_reduce_worker = FaceReducer()
405
+
406
+ # https://discuss.huggingface.co/t/how-to-serve-an-html-file/33921/2
407
+ # create a FastAPI app
408
+ app = FastAPI()
409
+ # create a static directory to store the static files
410
+ static_dir = Path('./gradio_cache')
411
+ static_dir.mkdir(parents=True, exist_ok=True)
412
+ app.mount("/static", StaticFiles(directory=static_dir), name="static")
413
+
414
+ demo = build_app()
415
+ app = gr.mount_gradio_app(app, demo, path="/")
416
+ uvicorn.run(app)
hy3dgen/shapegen/pipelines.py CHANGED
@@ -209,15 +209,13 @@ class Hunyuan3DDiTPipeline:
209
  original_model_path = model_path
210
  if not os.path.exists(model_path):
211
  # try local path
212
- base_dir = os.environ.get('HY3DGEN_MODELS', '/home/user//.cache/hy3dgen')
213
  model_path = os.path.expanduser(os.path.join(base_dir, model_path, 'hunyuan3d-dit-v2-0'))
214
  if not os.path.exists(model_path):
215
  try:
216
  import huggingface_hub
217
- path = huggingface_hub.snapshot_download(
218
- repo_id=original_model_path,
219
- resume_download=True
220
- )
221
  model_path = os.path.join(path, 'hunyuan3d-dit-v2-0')
222
  except ImportError:
223
  logger.warning(
 
209
  original_model_path = model_path
210
  if not os.path.exists(model_path):
211
  # try local path
212
+ base_dir = os.environ.get('HY3DGEN_MODELS', '~/.cache/hy3dgen')
213
  model_path = os.path.expanduser(os.path.join(base_dir, model_path, 'hunyuan3d-dit-v2-0'))
214
  if not os.path.exists(model_path):
215
  try:
216
  import huggingface_hub
217
+ # download from huggingface
218
+ path = huggingface_hub.snapshot_download(repo_id=original_model_path)
 
 
219
  model_path = os.path.join(path, 'hunyuan3d-dit-v2-0')
220
  except ImportError:
221
  logger.warning(
hy3dgen/texgen/pipelines.py CHANGED
@@ -61,7 +61,7 @@ class Hunyuan3DPaintPipeline:
61
  original_model_path = model_path
62
  if not os.path.exists(model_path):
63
  # try local path
64
- base_dir = os.environ.get('HY3DGEN_MODELS', '/home/user/.cache/hy3dgen')
65
  model_path = os.path.expanduser(os.path.join(base_dir, model_path))
66
 
67
  delight_model_path = os.path.join(model_path, 'hunyuan3d-delight-v2-0')
@@ -70,12 +70,10 @@ class Hunyuan3DPaintPipeline:
70
  if not os.path.exists(delight_model_path) or not os.path.exists(multiview_model_path):
71
  try:
72
  import huggingface_hub
73
- path = huggingface_hub.snapshot_download(
74
- repo_id=original_model_path,
75
- resume_download=True
76
- )
77
- delight_model_path = os.path.join(path, 'hunyuan3d-delight-v2-0')
78
- multiview_model_path = os.path.join(path, 'hunyuan3d-paint-v2-0')
79
  return cls(Hunyuan3DTexGenConfig(delight_model_path, multiview_model_path))
80
  except ImportError:
81
  logger.warning(
 
61
  original_model_path = model_path
62
  if not os.path.exists(model_path):
63
  # try local path
64
+ base_dir = os.environ.get('HY3DGEN_MODELS', '~/.cache/hy3dgen')
65
  model_path = os.path.expanduser(os.path.join(base_dir, model_path))
66
 
67
  delight_model_path = os.path.join(model_path, 'hunyuan3d-delight-v2-0')
 
70
  if not os.path.exists(delight_model_path) or not os.path.exists(multiview_model_path):
71
  try:
72
  import huggingface_hub
73
+ # download from huggingface
74
+ model_path = huggingface_hub.snapshot_download(repo_id=original_model_path)
75
+ delight_model_path = os.path.join(model_path, 'hunyuan3d-delight-v2-0')
76
+ multiview_model_path = os.path.join(model_path, 'hunyuan3d-paint-v2-0')
 
 
77
  return cls(Hunyuan3DTexGenConfig(delight_model_path, multiview_model_path))
78
  except ImportError:
79
  logger.warning(
minimal_demo.py CHANGED
@@ -26,7 +26,6 @@ import torch
26
 
27
  from hy3dgen.rembg import BackgroundRemover
28
  from hy3dgen.shapegen import Hunyuan3DDiTFlowMatchingPipeline, FaceReducer, FloaterRemover, DegenerateFaceRemover
29
- from hy3dgen.texgen import Hunyuan3DPaintPipeline
30
  from hy3dgen.text2image import HunyuanDiTPipeline
31
 
32
 
@@ -41,9 +40,14 @@ def image_to_3d(image_path='assets/demo.png'):
41
  mesh = FaceReducer()(mesh)
42
  mesh.export('mesh.glb')
43
 
44
- pipeline = Hunyuan3DPaintPipeline.from_pretrained(model_path)
45
- mesh = pipeline(mesh, image=image_path)
46
- mesh.export('texture.glb')
 
 
 
 
 
47
 
48
 
49
  def text_to_3d(prompt='a car'):
 
26
 
27
  from hy3dgen.rembg import BackgroundRemover
28
  from hy3dgen.shapegen import Hunyuan3DDiTFlowMatchingPipeline, FaceReducer, FloaterRemover, DegenerateFaceRemover
 
29
  from hy3dgen.text2image import HunyuanDiTPipeline
30
 
31
 
 
40
  mesh = FaceReducer()(mesh)
41
  mesh.export('mesh.glb')
42
 
43
+ try:
44
+ from hy3dgen.texgen import Hunyuan3DPaintPipeline
45
+ pipeline = Hunyuan3DPaintPipeline.from_pretrained(model_path)
46
+ mesh = pipeline(mesh, image=image_path)
47
+ mesh.export('texture.glb')
48
+ except Exception as e:
49
+ print(e)
50
+ print('Please try to install requirements by following README.md')
51
 
52
 
53
  def text_to_3d(prompt='a car'):
requirements.txt CHANGED
@@ -31,3 +31,5 @@ onnxruntime
31
  pygltflib
32
  sentencepiece
33
  gradio
 
 
 
31
  pygltflib
32
  sentencepiece
33
  gradio
34
+ uvicorn
35
+ fastapi