NicolasG2523 commited on
Commit
896f46c
·
verified ·
1 Parent(s): fdaad45

Upload gradio_app.py

Browse files
Files changed (1) hide show
  1. gradio_app.py +137 -41
gradio_app.py CHANGED
@@ -31,9 +31,10 @@ from hy3dgen.shapegen.utils import logger
31
 
32
  MAX_SEED = 1e7
33
 
 
 
34
  if True:
35
- import os
36
- import spaces
37
  import subprocess
38
  import sys
39
  import shlex
@@ -42,6 +43,38 @@ if True:
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 gen_save_folder(max_size=200):
47
  os.makedirs(SAVE_DIR, exist_ok=True)
@@ -102,17 +135,24 @@ def build_model_viewer_html(save_folder, height=660, width=790, textured=False):
102
  template_html = template_html.replace('#src#', f'{related_path}/')
103
  f.write(template_html)
104
 
105
- rel_path = os.path.relpath(output_html_path, SAVE_DIR)
106
- iframe_tag = f'<iframe src="/static/{rel_path}" height="{height}" width="100%" frameborder="0"></iframe>'
107
- print(
108
- f'Find html file {output_html_path}, {os.path.exists(output_html_path)}, relative HTML path is /static/{rel_path}')
109
-
110
- return f"""
111
- <div style='height: {height}; width: 100%;'>
112
- {iframe_tag}
113
- </div>
 
 
 
 
 
114
  """
115
 
 
 
116
  @spaces.GPU(duration=40)
117
  def _gen_shape(
118
  caption=None,
@@ -333,10 +373,12 @@ def shape_generation(
333
 
334
 
335
  def build_app():
 
336
 
337
  title_html = f"""
338
  <div style="font-size: 2em; font-weight: bold; text-align: center; margin-bottom: 5px">
339
- Genera tu modelo 3D desde fotos
 
340
  </div>
341
  """
342
  custom_css = """
@@ -350,6 +392,7 @@ def build_app():
350
  .mv-image .icon-wrap {
351
  width: 20px;
352
  }
 
353
  """
354
 
355
  with gr.Blocks(theme=gr.themes.Base(), title='Hunyuan-3D-2.0', analytics_enabled=False, css=custom_css) as demo:
@@ -369,38 +412,42 @@ def build_app():
369
  with gr.Tab('MultiView Prompt', visible=MV_MODE) as tab_mv:
370
  # gr.Label('Please upload at least one front image.')
371
  with gr.Row():
372
- mv_image_front = gr.Image(label='Frente', type='pil', image_mode='RGBA', height=140,
373
  min_width=100, elem_classes='mv-image')
374
- mv_image_back = gr.Image(label='Parte trasera', type='pil', image_mode='RGBA', height=140,
375
  min_width=100, elem_classes='mv-image')
376
  with gr.Row():
377
- mv_image_left = gr.Image(label='Izquierda', type='pil', image_mode='RGBA', height=140,
378
  min_width=100, elem_classes='mv-image')
379
- mv_image_right = gr.Image(label='Derecha', type='pil', image_mode='RGBA', height=140,
380
  min_width=100, elem_classes='mv-image')
381
 
382
  with gr.Row():
383
- btn = gr.Button(value='Generar modelo', variant='primary', min_width=100)
 
 
 
 
384
 
385
  with gr.Group():
386
  file_out = gr.File(label="File", visible=False)
387
  file_out2 = gr.File(label="File", visible=False)
388
 
389
  with gr.Tabs(selected='tab_options' if TURBO_MODE else 'tab_export'):
390
- with gr.Tab("Opciones", id='tab_options', visible=TURBO_MODE):
391
- gen_mode = gr.Radio(label='Modo de generacioón',
392
- info='Recomendacioón: Turbo por la mayoria, Fast para modelos complejos, Standard para uso cualquiera.',
393
  choices=['Turbo', 'Fast', 'Standard'], value='Turbo')
394
- decode_mode = gr.Radio(label='Modo de decoding',
395
- info='La resolución para la exportación de la malla desde el vectset generado',
396
  choices=['Low', 'Standard', 'High'],
397
  value='Standard')
398
- with gr.Tab('Opciones avanzadas', id='tab_advanced_options'):
399
  with gr.Row():
400
- check_box_rembg = gr.Checkbox(value=True, label='Eliminar fondo', min_width=100)
401
- randomize_seed = gr.Checkbox(label="Generar semilla aleatoria", value=True, min_width=100)
402
  seed = gr.Slider(
403
- label="Semmilla",
404
  minimum=0,
405
  maximum=MAX_SEED,
406
  step=1,
@@ -431,7 +478,7 @@ def build_app():
431
  file_export = gr.DownloadButton(label="Download", variant='primary',
432
  interactive=False, min_width=100)
433
 
434
- with gr.Column(scale=9):
435
  with gr.Tabs(selected='gen_mesh_panel') as tabs_output:
436
  with gr.Tab('Generated Mesh', id='gen_mesh_panel'):
437
  html_gen_mesh = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
@@ -440,6 +487,26 @@ def build_app():
440
  with gr.Tab('Mesh Statistic', id='stats_panel'):
441
  stats = gr.Json({}, label='Mesh Stats')
442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
443
 
444
  btn.click(
445
  shape_generation,
@@ -468,6 +535,33 @@ def build_app():
468
  outputs=[tabs_output],
469
  )
470
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
471
  def on_gen_mode_change(value):
472
  if value == 'Turbo':
473
  return gr.update(value=5)
@@ -552,6 +646,12 @@ if __name__ == '__main__':
552
  parser.add_argument('--low_vram_mode', action='store_true')
553
  args = parser.parse_args()
554
 
 
 
 
 
 
 
555
  args.enable_flashvdm = True
556
  SAVE_DIR = args.cache_path
557
  os.makedirs(SAVE_DIR, exist_ok=True)
@@ -565,7 +665,7 @@ if __name__ == '__main__':
565
  HTML_OUTPUT_PLACEHOLDER = f"""
566
  <div style='height: {650}px; width: 100%; border-radius: 8px; border-color: #e5e7eb; border-style: solid; border-width: 1px; display: flex; justify-content: center; align-items: center;'>
567
  <div style='text-align: center; font-size: 16px; color: #6b7280;'>
568
- <p style="color: #8d8d8d;">Carga tus fotos para generar el modelo 3D</p>
569
  </div>
570
  </div>
571
  """
@@ -575,7 +675,12 @@ if __name__ == '__main__':
575
  border-color: #e5e7eb; order-style: solid; border-width: 1px;'>
576
  </div>
577
  """
578
-
 
 
 
 
 
579
  SUPPORTED_FORMATS = ['glb', 'obj', 'ply', 'stl']
580
 
581
  HAS_TEXTUREGEN = False
@@ -586,12 +691,7 @@ if __name__ == '__main__':
586
  texgen_worker = Hunyuan3DPaintPipeline.from_pretrained(args.texgen_model_path)
587
  if args.low_vram_mode:
588
  texgen_worker.enable_model_cpu_offload()
589
- # Not help much, ignore for now.
590
- # if args.compile:
591
- # texgen_worker.models['delight_model'].pipeline.unet.compile()
592
- # texgen_worker.models['delight_model'].pipeline.vae.compile()
593
- # texgen_worker.models['multiview_model'].pipeline.unet.compile()
594
- # texgen_worker.models['multiview_model'].pipeline.vae.compile()
595
  HAS_TEXTUREGEN = True
596
  except Exception as e:
597
  print(e)
@@ -628,17 +728,13 @@ if __name__ == '__main__':
628
  degenerate_face_remove_worker = DegenerateFaceRemover()
629
  face_reduce_worker = FaceReducer()
630
 
631
- # https://discuss.huggingface.co/t/how-to-serve-an-html-file/33921/2
632
- # create a FastAPI app
633
- app = FastAPI()
634
  # create a static directory to store the static files
635
  static_dir = Path(SAVE_DIR).absolute()
636
  static_dir.mkdir(parents=True, exist_ok=True)
637
- app.mount("/static", StaticFiles(directory=static_dir, html=True), name="static")
638
  shutil.copytree('./assets/env_maps', os.path.join(static_dir, 'env_maps'), dirs_exist_ok=True)
639
 
 
640
  if args.low_vram_mode:
641
  torch.cuda.empty_cache()
642
  demo = build_app()
643
- app = gr.mount_gradio_app(app, demo, path="/")
644
- uvicorn.run(app, host=args.host, port=args.port)
 
31
 
32
  MAX_SEED = 1e7
33
 
34
+ import spaces
35
+
36
  if True:
37
+ import os
 
38
  import subprocess
39
  import sys
40
  import shlex
 
43
  print('install custom')
44
  subprocess.run(shlex.split("pip install custom_rasterizer-0.1-cp310-cp310-linux_x86_64.whl"), check=True)
45
 
46
+ @spaces.GPU
47
+ def my_gpu_function():
48
+ pass
49
+
50
+ def get_example_img_list():
51
+ print('Loading example img list ...')
52
+ return sorted(glob('./assets/example_images/**/*.png', recursive=True))
53
+
54
+
55
+ def get_example_txt_list():
56
+ print('Loading example txt list ...')
57
+ txt_list = list()
58
+ for line in open('./assets/example_prompts.txt', encoding='utf-8'):
59
+ txt_list.append(line.strip())
60
+ return txt_list
61
+
62
+
63
+ def get_example_mv_list():
64
+ print('Loading example mv list ...')
65
+ mv_list = list()
66
+ root = './assets/example_mv_images'
67
+ for mv_dir in os.listdir(root):
68
+ view_list = []
69
+ for view in ['front', 'back', 'left', 'right']:
70
+ path = os.path.join(root, mv_dir, f'{view}.png')
71
+ if os.path.exists(path):
72
+ view_list.append(path)
73
+ else:
74
+ view_list.append(None)
75
+ mv_list.append(view_list)
76
+ return mv_list
77
+
78
 
79
  def gen_save_folder(max_size=200):
80
  os.makedirs(SAVE_DIR, exist_ok=True)
 
135
  template_html = template_html.replace('#src#', f'{related_path}/')
136
  f.write(template_html)
137
 
138
+ mesh_file = os.path.join(save_folder, "white_mesh.html")
139
+ # Encode the GLB file as base64 to embed directly in the HTML
140
+ with open(mesh_file, "rb") as f:
141
+ glb_data = f.read()
142
+ glb_base64 = base64.b64encode(glb_data).decode("utf-8")
143
+
144
+ model_viewer_html = f"""
145
+ <script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>
146
+ <model-viewer src="data:model/gltf-binary;base64,{glb_base64}"
147
+ alt="3D Model"
148
+ camera-controls
149
+ auto-rotate
150
+ style="height: {height}px; width: {width}px;">
151
+ </model-viewer>
152
  """
153
 
154
+ return model_viewer_html
155
+
156
  @spaces.GPU(duration=40)
157
  def _gen_shape(
158
  caption=None,
 
373
 
374
 
375
  def build_app():
376
+ title = 'Generación de modelo basado en imágenes (de 1 a 4 vistas)'
377
 
378
  title_html = f"""
379
  <div style="font-size: 2em; font-weight: bold; text-align: center; margin-bottom: 5px">
380
+
381
+ {title}
382
  </div>
383
  """
384
  custom_css = """
 
392
  .mv-image .icon-wrap {
393
  width: 20px;
394
  }
395
+
396
  """
397
 
398
  with gr.Blocks(theme=gr.themes.Base(), title='Hunyuan-3D-2.0', analytics_enabled=False, css=custom_css) as demo:
 
412
  with gr.Tab('MultiView Prompt', visible=MV_MODE) as tab_mv:
413
  # gr.Label('Please upload at least one front image.')
414
  with gr.Row():
415
+ mv_image_front = gr.Image(label='Front', type='pil', image_mode='RGBA', height=140,
416
  min_width=100, elem_classes='mv-image')
417
+ mv_image_back = gr.Image(label='Back', type='pil', image_mode='RGBA', height=140,
418
  min_width=100, elem_classes='mv-image')
419
  with gr.Row():
420
+ mv_image_left = gr.Image(label='Left', type='pil', image_mode='RGBA', height=140,
421
  min_width=100, elem_classes='mv-image')
422
+ mv_image_right = gr.Image(label='Right', type='pil', image_mode='RGBA', height=140,
423
  min_width=100, elem_classes='mv-image')
424
 
425
  with gr.Row():
426
+ btn = gr.Button(value='Gen Shape', variant='primary', min_width=100)
427
+ btn_all = gr.Button(value='Gen Textured Shape',
428
+ variant='primary',
429
+ visible=HAS_TEXTUREGEN,
430
+ min_width=100)
431
 
432
  with gr.Group():
433
  file_out = gr.File(label="File", visible=False)
434
  file_out2 = gr.File(label="File", visible=False)
435
 
436
  with gr.Tabs(selected='tab_options' if TURBO_MODE else 'tab_export'):
437
+ with gr.Tab("Options", id='tab_options', visible=TURBO_MODE):
438
+ gen_mode = gr.Radio(label='Generation Mode',
439
+ info='Recommendation: Turbo for most cases, Fast for very complex cases, Standard seldom use.',
440
  choices=['Turbo', 'Fast', 'Standard'], value='Turbo')
441
+ decode_mode = gr.Radio(label='Decoding Mode',
442
+ info='The resolution for exporting mesh from generated vectset',
443
  choices=['Low', 'Standard', 'High'],
444
  value='Standard')
445
+ with gr.Tab('Advanced Options', id='tab_advanced_options'):
446
  with gr.Row():
447
+ check_box_rembg = gr.Checkbox(value=True, label='Remove Background', min_width=100)
448
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True, min_width=100)
449
  seed = gr.Slider(
450
+ label="Seed",
451
  minimum=0,
452
  maximum=MAX_SEED,
453
  step=1,
 
478
  file_export = gr.DownloadButton(label="Download", variant='primary',
479
  interactive=False, min_width=100)
480
 
481
+ with gr.Column(scale=6):
482
  with gr.Tabs(selected='gen_mesh_panel') as tabs_output:
483
  with gr.Tab('Generated Mesh', id='gen_mesh_panel'):
484
  html_gen_mesh = gr.HTML(HTML_OUTPUT_PLACEHOLDER, label='Output')
 
487
  with gr.Tab('Mesh Statistic', id='stats_panel'):
488
  stats = gr.Json({}, label='Mesh Stats')
489
 
490
+ with gr.Column(scale=3 if MV_MODE else 2):
491
+ with gr.Tabs(selected='tab_img_gallery') as gallery:
492
+ with gr.Tab('Image to 3D Gallery', id='tab_img_gallery', visible=not MV_MODE) as tab_gi:
493
+ with gr.Row():
494
+ gr.Examples(examples=example_is, inputs=[image],
495
+ label=None, examples_per_page=18)
496
+
497
+ with gr.Tab('Text to 3D Gallery', id='tab_txt_gallery', visible=HAS_T2I and not MV_MODE) as tab_gt:
498
+ with gr.Row():
499
+ gr.Examples(examples=example_ts, inputs=[caption],
500
+ label=None, examples_per_page=18)
501
+ with gr.Tab('MultiView to 3D Gallery', id='tab_mv_gallery', visible=MV_MODE) as tab_mv:
502
+ with gr.Row():
503
+ gr.Examples(examples=example_mvs,
504
+ inputs=[mv_image_front, mv_image_back, mv_image_left, mv_image_right],
505
+ label=None, examples_per_page=6)
506
+
507
+ tab_ip.select(fn=lambda: gr.update(selected='tab_img_gallery'), outputs=gallery)
508
+ if HAS_T2I:
509
+ tab_tp.select(fn=lambda: gr.update(selected='tab_txt_gallery'), outputs=gallery)
510
 
511
  btn.click(
512
  shape_generation,
 
535
  outputs=[tabs_output],
536
  )
537
 
538
+ btn_all.click(
539
+ generation_all,
540
+ inputs=[
541
+ caption,
542
+ image,
543
+ mv_image_front,
544
+ mv_image_back,
545
+ mv_image_left,
546
+ mv_image_right,
547
+ num_steps,
548
+ cfg_scale,
549
+ seed,
550
+ octree_resolution,
551
+ check_box_rembg,
552
+ num_chunks,
553
+ randomize_seed,
554
+ ],
555
+ outputs=[file_out, file_out2, html_gen_mesh, stats, seed]
556
+ ).then(
557
+ lambda: (gr.update(visible=True, value=True), gr.update(interactive=False), gr.update(interactive=True),
558
+ gr.update(interactive=False)),
559
+ outputs=[export_texture, reduce_face, confirm_export, file_export],
560
+ ).then(
561
+ lambda: gr.update(selected='gen_mesh_panel'),
562
+ outputs=[tabs_output],
563
+ )
564
+
565
  def on_gen_mode_change(value):
566
  if value == 'Turbo':
567
  return gr.update(value=5)
 
646
  parser.add_argument('--low_vram_mode', action='store_true')
647
  args = parser.parse_args()
648
 
649
+ try:
650
+ port = int(args.port)
651
+ except ValueError:
652
+ print(f"Invalid port argument detected: {args.port} — using default 7860")
653
+ port = 7860
654
+
655
  args.enable_flashvdm = True
656
  SAVE_DIR = args.cache_path
657
  os.makedirs(SAVE_DIR, exist_ok=True)
 
665
  HTML_OUTPUT_PLACEHOLDER = f"""
666
  <div style='height: {650}px; width: 100%; border-radius: 8px; border-color: #e5e7eb; border-style: solid; border-width: 1px; display: flex; justify-content: center; align-items: center;'>
667
  <div style='text-align: center; font-size: 16px; color: #6b7280;'>
668
+ <p style="color: #8d8d8d;">Bienvenido a 3DMarket</p>
669
  </div>
670
  </div>
671
  """
 
675
  border-color: #e5e7eb; order-style: solid; border-width: 1px;'>
676
  </div>
677
  """
678
+
679
+ demo = gr.Interface(fn=my_gpu_function, inputs=[], outputs="text")
680
+ example_is = get_example_img_list()
681
+ example_ts = get_example_txt_list()
682
+ example_mvs = get_example_mv_list()
683
+
684
  SUPPORTED_FORMATS = ['glb', 'obj', 'ply', 'stl']
685
 
686
  HAS_TEXTUREGEN = False
 
691
  texgen_worker = Hunyuan3DPaintPipeline.from_pretrained(args.texgen_model_path)
692
  if args.low_vram_mode:
693
  texgen_worker.enable_model_cpu_offload()
694
+
 
 
 
 
 
695
  HAS_TEXTUREGEN = True
696
  except Exception as e:
697
  print(e)
 
728
  degenerate_face_remove_worker = DegenerateFaceRemover()
729
  face_reduce_worker = FaceReducer()
730
 
 
 
 
731
  # create a static directory to store the static files
732
  static_dir = Path(SAVE_DIR).absolute()
733
  static_dir.mkdir(parents=True, exist_ok=True)
 
734
  shutil.copytree('./assets/env_maps', os.path.join(static_dir, 'env_maps'), dirs_exist_ok=True)
735
 
736
+
737
  if args.low_vram_mode:
738
  torch.cuda.empty_cache()
739
  demo = build_app()
740
+ demo.launch()