ZeqiangLai commited on
Commit
3c9cde1
·
verified ·
1 Parent(s): 6b88e7a

Update gradio_app.py

Browse files
Files changed (1) hide show
  1. gradio_app.py +74 -30
gradio_app.py CHANGED
@@ -1,10 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import random
3
  import shutil
4
  import time
5
  from glob import glob
6
  from pathlib import Path
7
- import uuid
8
 
9
  import gradio as gr
10
  import torch
@@ -12,6 +25,7 @@ import trimesh
12
  import uvicorn
13
  from fastapi import FastAPI
14
  from fastapi.staticfiles import StaticFiles
 
15
 
16
  from hy3dgen.shapegen.utils import logger
17
 
@@ -28,6 +42,7 @@ if True:
28
  print('install custom')
29
  subprocess.run(shlex.split("pip install custom_rasterizer-0.1-cp310-cp310-linux_x86_64.whl"), check=True)
30
 
 
31
  def get_example_img_list():
32
  print('Loading example img list ...')
33
  return sorted(glob('./assets/example_images/**/*.png', recursive=True))
@@ -47,7 +62,7 @@ def get_example_mv_list():
47
  root = './assets/example_mv_images'
48
  for mv_dir in os.listdir(root):
49
  view_list = []
50
- for view in ['正视图', '背视图', '左视图', '右视图']:
51
  path = os.path.join(root, mv_dir, f'{view}.png')
52
  if os.path.exists(path):
53
  view_list.append(path)
@@ -57,18 +72,6 @@ def get_example_mv_list():
57
  return mv_list
58
 
59
 
60
- # def gen_save_folder(max_size=60):
61
- # os.makedirs(SAVE_DIR, exist_ok=True)
62
- # exists = set(int(_) for _ in os.listdir(SAVE_DIR) if _.isdigit())
63
- # cur_id = min(set(range(max_size)) - exists) if len(exists) < max_size else -1
64
- # if os.path.exists(f"{SAVE_DIR}/{(cur_id + 1) % max_size}"):
65
- # shutil.rmtree(f"{SAVE_DIR}/{(cur_id + 1) % max_size}")
66
- # print(f"remove {SAVE_DIR}/{(cur_id + 1) % max_size} success !!!")
67
- # save_folder = f"{SAVE_DIR}/{max(0, cur_id)}"
68
- # os.makedirs(save_folder, exist_ok=True)
69
- # print(f"mkdir {save_folder} suceess !!!")
70
- # return save_folder
71
-
72
  def gen_save_folder(max_size=200):
73
  os.makedirs(SAVE_DIR, exist_ok=True)
74
 
@@ -139,7 +142,7 @@ def build_model_viewer_html(save_folder, height=660, width=790, textured=False):
139
  </div>
140
  """
141
 
142
- @spaces.GPU(duration=60)
143
  def _gen_shape(
144
  caption=None,
145
  image=None,
@@ -246,7 +249,7 @@ def _gen_shape(
246
  main_image = image if not MV_MODE else image['front']
247
  return mesh, main_image, save_folder, stats, seed
248
 
249
- @spaces.GPU(duration=70)
250
  def generation_all(
251
  caption=None,
252
  image=None,
@@ -301,7 +304,8 @@ def generation_all(
301
  path_textured = export_mesh(textured_mesh, save_folder, textured=True)
302
  model_viewer_html_textured = build_model_viewer_html(save_folder, height=HTML_HEIGHT, width=HTML_WIDTH,
303
  textured=True)
304
-
 
305
  return (
306
  gr.update(value=path),
307
  gr.update(value=path_textured),
@@ -310,7 +314,7 @@ def generation_all(
310
  seed,
311
  )
312
 
313
- @spaces.GPU(duration=60)
314
  def shape_generation(
315
  caption=None,
316
  image=None,
@@ -347,7 +351,8 @@ def shape_generation(
347
 
348
  path = export_mesh(mesh, save_folder, textured=False)
349
  model_viewer_html = build_model_viewer_html(save_folder, height=HTML_HEIGHT, width=HTML_WIDTH)
350
-
 
351
  return (
352
  gr.update(value=path),
353
  model_viewer_html,
@@ -362,6 +367,8 @@ def build_app():
362
  title = 'Hunyuan3D-2mv: Image to 3D Generation with 1-4 Views'
363
  if 'mini' in args.subfolder:
364
  title = 'Hunyuan3D-2mini: Strong 0.6B Image to Shape Generator'
 
 
365
 
366
  title_html = f"""
367
  <div style="font-size: 2em; font-weight: bold; text-align: center; margin-bottom: 5px">
@@ -386,11 +393,11 @@ def build_app():
386
  .mv-image button .wrap {
387
  font-size: 10px;
388
  }
389
-
390
  .mv-image .icon-wrap {
391
  width: 20px;
392
  }
393
-
394
  """
395
 
396
  with gr.Blocks(theme=gr.themes.Base(), title='Hunyuan-3D-2.0', analytics_enabled=False, css=custom_css) as demo:
@@ -430,7 +437,15 @@ def build_app():
430
  file_out = gr.File(label="File", visible=False)
431
  file_out2 = gr.File(label="File", visible=False)
432
 
433
- with gr.Tabs(selected='tab_export'):
 
 
 
 
 
 
 
 
434
  with gr.Tab('Advanced Options', id='tab_advanced_options'):
435
  with gr.Row():
436
  check_box_rembg = gr.Checkbox(value=True, label='Remove Background', min_width=100)
@@ -446,14 +461,13 @@ def build_app():
446
  with gr.Row():
447
  num_steps = gr.Slider(maximum=100,
448
  minimum=1,
449
- value=30,
450
  step=1, label='Inference Steps')
451
  octree_resolution = gr.Slider(maximum=512, minimum=16, value=256, label='Octree Resolution')
452
  with gr.Row():
453
  cfg_scale = gr.Number(value=5.0, label='Guidance Scale', min_width=100)
454
- num_chunks = gr.Slider(maximum=5000000, minimum=1000, value=200000,
455
  label='Number of Chunks', min_width=100)
456
-
457
  with gr.Tab("Export", id='tab_export'):
458
  with gr.Row():
459
  file_type = gr.Dropdown(label='File Type', choices=SUPPORTED_FORMATS,
@@ -573,6 +587,26 @@ def build_app():
573
  outputs=[tabs_output],
574
  )
575
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
576
  def on_export_click(file_out, file_out2, file_type, reduce_face, export_texture, target_face_num):
577
  if file_out is None:
578
  raise gr.Error('Please generate a mesh first.')
@@ -628,18 +662,22 @@ if __name__ == '__main__':
628
  parser.add_argument('--port', type=int, default=7860)
629
  parser.add_argument('--host', type=str, default='0.0.0.0')
630
  parser.add_argument('--device', type=str, default='cuda')
631
- parser.add_argument('--mc_algo', type=str, default='dmc')
632
  parser.add_argument('--cache-path', type=str, default='gradio_cache')
633
  parser.add_argument('--enable_t23d', action='store_true')
634
  parser.add_argument('--disable_tex', action='store_true')
 
635
  parser.add_argument('--compile', action='store_true')
 
636
  args = parser.parse_args()
637
 
 
638
  SAVE_DIR = args.cache_path
639
  os.makedirs(SAVE_DIR, exist_ok=True)
640
 
641
  CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
642
  MV_MODE = 'mv' in args.model_path
 
643
 
644
  HTML_HEIGHT = 690 if MV_MODE else 650
645
  HTML_WIDTH = 500
@@ -662,14 +700,15 @@ if __name__ == '__main__':
662
  example_mvs = get_example_mv_list()
663
 
664
  SUPPORTED_FORMATS = ['glb', 'obj', 'ply', 'stl']
665
-
666
- args.disable_tex = True
667
  HAS_TEXTUREGEN = False
668
  if not args.disable_tex:
669
  try:
670
  from hy3dgen.texgen import Hunyuan3DPaintPipeline
671
 
672
  texgen_worker = Hunyuan3DPaintPipeline.from_pretrained(args.texgen_model_path)
 
 
673
  # Not help much, ignore for now.
674
  # if args.compile:
675
  # texgen_worker.models['delight_model'].pipeline.unet.compile()
@@ -699,9 +738,12 @@ if __name__ == '__main__':
699
  i23d_worker = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained(
700
  args.model_path,
701
  subfolder=args.subfolder,
702
- use_safetensors=False,
703
  device=args.device,
704
  )
 
 
 
705
  if args.compile:
706
  i23d_worker.compile()
707
 
@@ -718,6 +760,8 @@ if __name__ == '__main__':
718
  app.mount("/static", StaticFiles(directory=static_dir, html=True), name="static")
719
  shutil.copytree('./assets/env_maps', os.path.join(static_dir, 'env_maps'), dirs_exist_ok=True)
720
 
 
 
721
  demo = build_app()
722
  app = gr.mount_gradio_app(app, demo, path="/")
723
- uvicorn.run(app, host=args.host, port=args.port)
 
1
+ # Hunyuan 3D is licensed under the TENCENT HUNYUAN NON-COMMERCIAL LICENSE AGREEMENT
2
+ # except for the third-party components listed below.
3
+ # Hunyuan 3D does not impose any additional limitations beyond what is outlined
4
+ # in the repsective licenses of these third-party components.
5
+ # Users must comply with all terms and conditions of original licenses of these third-party
6
+ # components and must ensure that the usage of the third party components adheres to
7
+ # all relevant laws and regulations.
8
+
9
+ # For avoidance of doubts, Hunyuan 3D means the large language models and
10
+ # their software and algorithms, including trained model weights, parameters (including
11
+ # optimizer states), machine-learning model code, inference-enabling code, training-enabling code,
12
+ # fine-tuning enabling code and other elements of the foregoing made publicly available
13
+ # by Tencent in accordance with TENCENT HUNYUAN COMMUNITY LICENSE AGREEMENT.
14
+
15
  import os
16
  import random
17
  import shutil
18
  import time
19
  from glob import glob
20
  from pathlib import Path
 
21
 
22
  import gradio as gr
23
  import torch
 
25
  import uvicorn
26
  from fastapi import FastAPI
27
  from fastapi.staticfiles import StaticFiles
28
+ import uuid
29
 
30
  from hy3dgen.shapegen.utils import logger
31
 
 
42
  print('install custom')
43
  subprocess.run(shlex.split("pip install custom_rasterizer-0.1-cp310-cp310-linux_x86_64.whl"), check=True)
44
 
45
+
46
  def get_example_img_list():
47
  print('Loading example img list ...')
48
  return sorted(glob('./assets/example_images/**/*.png', recursive=True))
 
62
  root = './assets/example_mv_images'
63
  for mv_dir in os.listdir(root):
64
  view_list = []
65
+ for view in ['front', 'back', 'left', 'right']:
66
  path = os.path.join(root, mv_dir, f'{view}.png')
67
  if os.path.exists(path):
68
  view_list.append(path)
 
72
  return mv_list
73
 
74
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  def gen_save_folder(max_size=200):
76
  os.makedirs(SAVE_DIR, exist_ok=True)
77
 
 
142
  </div>
143
  """
144
 
145
+
146
  def _gen_shape(
147
  caption=None,
148
  image=None,
 
249
  main_image = image if not MV_MODE else image['front']
250
  return mesh, main_image, save_folder, stats, seed
251
 
252
+
253
  def generation_all(
254
  caption=None,
255
  image=None,
 
304
  path_textured = export_mesh(textured_mesh, save_folder, textured=True)
305
  model_viewer_html_textured = build_model_viewer_html(save_folder, height=HTML_HEIGHT, width=HTML_WIDTH,
306
  textured=True)
307
+ if args.low_vram_mode:
308
+ torch.cuda.empty_cache()
309
  return (
310
  gr.update(value=path),
311
  gr.update(value=path_textured),
 
314
  seed,
315
  )
316
 
317
+
318
  def shape_generation(
319
  caption=None,
320
  image=None,
 
351
 
352
  path = export_mesh(mesh, save_folder, textured=False)
353
  model_viewer_html = build_model_viewer_html(save_folder, height=HTML_HEIGHT, width=HTML_WIDTH)
354
+ if args.low_vram_mode:
355
+ torch.cuda.empty_cache()
356
  return (
357
  gr.update(value=path),
358
  model_viewer_html,
 
367
  title = 'Hunyuan3D-2mv: Image to 3D Generation with 1-4 Views'
368
  if 'mini' in args.subfolder:
369
  title = 'Hunyuan3D-2mini: Strong 0.6B Image to Shape Generator'
370
+ if TURBO_MODE:
371
+ title = title.replace(':', '-Turbo: Fast ')
372
 
373
  title_html = f"""
374
  <div style="font-size: 2em; font-weight: bold; text-align: center; margin-bottom: 5px">
 
393
  .mv-image button .wrap {
394
  font-size: 10px;
395
  }
396
+
397
  .mv-image .icon-wrap {
398
  width: 20px;
399
  }
400
+
401
  """
402
 
403
  with gr.Blocks(theme=gr.themes.Base(), title='Hunyuan-3D-2.0', analytics_enabled=False, css=custom_css) as demo:
 
437
  file_out = gr.File(label="File", visible=False)
438
  file_out2 = gr.File(label="File", visible=False)
439
 
440
+ with gr.Tabs(selected='tab_options' if TURBO_MODE else 'tab_export'):
441
+ with gr.Tab("Options", id='tab_options', visible=TURBO_MODE):
442
+ gen_mode = gr.Radio(label='Generation Mode',
443
+ info='Recommendation: Turbo for most cases, Fast for very complex cases, Standard seldom use.',
444
+ choices=['Turbo', 'Fast', 'Standard'], value='Turbo')
445
+ decode_mode = gr.Radio(label='Decoding Mode',
446
+ info='The resolution for exporting mesh from generated vectset',
447
+ choices=['Low', 'Standard', 'High'],
448
+ value='Standard')
449
  with gr.Tab('Advanced Options', id='tab_advanced_options'):
450
  with gr.Row():
451
  check_box_rembg = gr.Checkbox(value=True, label='Remove Background', min_width=100)
 
461
  with gr.Row():
462
  num_steps = gr.Slider(maximum=100,
463
  minimum=1,
464
+ value=5 if 'turbo' in args.subfolder else 30,
465
  step=1, label='Inference Steps')
466
  octree_resolution = gr.Slider(maximum=512, minimum=16, value=256, label='Octree Resolution')
467
  with gr.Row():
468
  cfg_scale = gr.Number(value=5.0, label='Guidance Scale', min_width=100)
469
+ num_chunks = gr.Slider(maximum=5000000, minimum=1000, value=8000,
470
  label='Number of Chunks', min_width=100)
 
471
  with gr.Tab("Export", id='tab_export'):
472
  with gr.Row():
473
  file_type = gr.Dropdown(label='File Type', choices=SUPPORTED_FORMATS,
 
587
  outputs=[tabs_output],
588
  )
589
 
590
+ def on_gen_mode_change(value):
591
+ if value == 'Turbo':
592
+ return gr.update(value=5)
593
+ elif value == 'Fast':
594
+ return gr.update(value=10)
595
+ else:
596
+ return gr.update(value=30)
597
+
598
+ gen_mode.change(on_gen_mode_change, inputs=[gen_mode], outputs=[num_steps])
599
+
600
+ def on_decode_mode_change(value):
601
+ if value == 'Low':
602
+ return gr.update(value=196)
603
+ elif value == 'Standard':
604
+ return gr.update(value=256)
605
+ else:
606
+ return gr.update(value=384)
607
+
608
+ decode_mode.change(on_decode_mode_change, inputs=[decode_mode], outputs=[octree_resolution])
609
+
610
  def on_export_click(file_out, file_out2, file_type, reduce_face, export_texture, target_face_num):
611
  if file_out is None:
612
  raise gr.Error('Please generate a mesh first.')
 
662
  parser.add_argument('--port', type=int, default=7860)
663
  parser.add_argument('--host', type=str, default='0.0.0.0')
664
  parser.add_argument('--device', type=str, default='cuda')
665
+ parser.add_argument('--mc_algo', type=str, default='mc')
666
  parser.add_argument('--cache-path', type=str, default='gradio_cache')
667
  parser.add_argument('--enable_t23d', action='store_true')
668
  parser.add_argument('--disable_tex', action='store_true')
669
+ parser.add_argument('--enable_flashvdm', action='store_true')
670
  parser.add_argument('--compile', action='store_true')
671
+ parser.add_argument('--low_vram_mode', action='store_true')
672
  args = parser.parse_args()
673
 
674
+ args.enable_flashvdm = True
675
  SAVE_DIR = args.cache_path
676
  os.makedirs(SAVE_DIR, exist_ok=True)
677
 
678
  CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
679
  MV_MODE = 'mv' in args.model_path
680
+ TURBO_MODE = 'turbo' in args.subfolder
681
 
682
  HTML_HEIGHT = 690 if MV_MODE else 650
683
  HTML_WIDTH = 500
 
700
  example_mvs = get_example_mv_list()
701
 
702
  SUPPORTED_FORMATS = ['glb', 'obj', 'ply', 'stl']
703
+
 
704
  HAS_TEXTUREGEN = False
705
  if not args.disable_tex:
706
  try:
707
  from hy3dgen.texgen import Hunyuan3DPaintPipeline
708
 
709
  texgen_worker = Hunyuan3DPaintPipeline.from_pretrained(args.texgen_model_path)
710
+ if args.low_vram_mode:
711
+ texgen_worker.enable_model_cpu_offload()
712
  # Not help much, ignore for now.
713
  # if args.compile:
714
  # texgen_worker.models['delight_model'].pipeline.unet.compile()
 
738
  i23d_worker = Hunyuan3DDiTFlowMatchingPipeline.from_pretrained(
739
  args.model_path,
740
  subfolder=args.subfolder,
741
+ use_safetensors=True,
742
  device=args.device,
743
  )
744
+ if args.enable_flashvdm:
745
+ mc_algo = 'mc' if args.device in ['cpu', 'mps'] else args.mc_algo
746
+ i23d_worker.enable_flashvdm(mc_algo=mc_algo)
747
  if args.compile:
748
  i23d_worker.compile()
749
 
 
760
  app.mount("/static", StaticFiles(directory=static_dir, html=True), name="static")
761
  shutil.copytree('./assets/env_maps', os.path.join(static_dir, 'env_maps'), dirs_exist_ok=True)
762
 
763
+ if args.low_vram_mode:
764
+ torch.cuda.empty_cache()
765
  demo = build_app()
766
  app = gr.mount_gradio_app(app, demo, path="/")
767
+ uvicorn.run(app, host=args.host, port=args.port, workers=1)