bluestyle97 cbensimon HF staff commited on
Commit
8167a6c
1 Parent(s): 3f48d77

Working ZeroGPU version (#6)

Browse files

- Working ZeroGPU version (9ae28d8d321fe12e90eecf0e5506325c245274e3)
- Update freesplatter/webui/runner.py (0d0baebb992391cede34eb2ad8ffed970c5697ef)
- Update freesplatter/webui/tab_img_to_3d.py (0dd1fb37cf6a2c4f916410a260f27ee22b6cf101)
- Create open3d_zerogpu_fix.py (04a21477f8ecbd98eb713d7e1b4b35ca7e9da1bc)
- Update app.py (88c07bd9d42992b9f0d2d820b61494306c3fe465)


Co-authored-by: Charles Bensimon <cbensimon@users.noreply.huggingface.co>

app.py CHANGED
@@ -1,6 +1,8 @@
 
1
  import os
2
  if 'OMP_NUM_THREADS' not in os.environ:
3
  os.environ['OMP_NUM_THREADS'] = '16'
 
4
  import torch
5
  import subprocess
6
  import gradio as gr
@@ -11,30 +13,16 @@ from freesplatter.webui.runner import FreeSplatterRunner
11
  from freesplatter.webui.tab_img_to_3d import create_interface_img_to_3d
12
 
13
 
14
- def install_cuda_toolkit():
15
- CUDA_TOOLKIT_URL = "https://developer.download.nvidia.com/compute/cuda/12.1.0/local_installers/cuda_12.1.0_530.30.02_linux.run"
16
- CUDA_TOOLKIT_FILE = "/tmp/%s" % os.path.basename(CUDA_TOOLKIT_URL)
17
- subprocess.call(["wget", "-q", CUDA_TOOLKIT_URL, "-O", CUDA_TOOLKIT_FILE])
18
- subprocess.call(["chmod", "+x", CUDA_TOOLKIT_FILE])
19
- subprocess.call([CUDA_TOOLKIT_FILE, "--silent", "--toolkit"])
20
-
21
- os.environ["CUDA_HOME"] = "/usr/local/cuda"
22
- os.environ["PATH"] = "%s/bin:%s" % (os.environ["CUDA_HOME"], os.environ["PATH"])
23
- os.environ["LD_LIBRARY_PATH"] = "%s/lib:%s" % (
24
- os.environ["CUDA_HOME"],
25
- "" if "LD_LIBRARY_PATH" not in os.environ else os.environ["LD_LIBRARY_PATH"],
26
- )
27
- # Fix: arch_list[-1] += '+PTX'; IndexError: list index out of range
28
- os.environ["TORCH_CUDA_ARCH_LIST"] = "8.0;8.6"
29
-
30
- install_cuda_toolkit()
31
-
32
-
33
  torch.set_grad_enabled(False)
34
  device = torch.device('cuda')
35
  runner = FreeSplatterRunner(device)
36
 
37
 
 
 
 
 
 
38
  _HEADER_ = '''
39
  # FreeSplatter 🤗 Gradio Demo
40
  \n\nOfficial demo of the paper [FreeSplatter: Pose-free Gaussian Splatting for Sparse-view 3D Reconstruction](https://arxiv.org/abs/2404.07191). [[Github]](https://github.com/TencentARC/FreeSplatter)
@@ -82,18 +70,15 @@ with gr.Blocks(analytics_enabled=False, title='FreeSplatter Demo') as demo:
82
  with gr.Tabs() as sub_tabs_img_to_3d:
83
  with gr.TabItem('Hunyuan3D Std', id='tab_hunyuan3d_std'):
84
  _, var_img_to_3d_hunyuan3d_std = create_interface_img_to_3d(
85
- runner.run_segmentation,
86
- runner.run_img_to_3d,
87
  model='Hunyuan3D Std')
88
  with gr.TabItem('Zero123++ v1.1', id='tab_zero123plus_v11'):
89
  _, var_img_to_3d_zero123plus_v11 = create_interface_img_to_3d(
90
- runner.run_segmentation,
91
- runner.run_img_to_3d,
92
  model='Zero123++ v1.1')
93
  with gr.TabItem('Zero123++ v1.2', id='tab_zero123plus_v12'):
94
  _, var_img_to_3d_zero123plus_v12 = create_interface_img_to_3d(
95
- runner.run_segmentation,
96
- runner.run_img_to_3d,
97
  model='Zero123++ v1.2')
98
 
99
  gr.Markdown(_CITE_)
 
1
+ import open3d_zerogpu_fix
2
  import os
3
  if 'OMP_NUM_THREADS' not in os.environ:
4
  os.environ['OMP_NUM_THREADS'] = '16'
5
+ import spaces
6
  import torch
7
  import subprocess
8
  import gradio as gr
 
13
  from freesplatter.webui.tab_img_to_3d import create_interface_img_to_3d
14
 
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  torch.set_grad_enabled(False)
17
  device = torch.device('cuda')
18
  runner = FreeSplatterRunner(device)
19
 
20
 
21
+ @spaces.GPU(duration=120)
22
+ def run_img_to_3d(*args):
23
+ yield from runner.run_img_to_3d(*args, cache_dir=gr.utils.get_upload_folder())
24
+
25
+
26
  _HEADER_ = '''
27
  # FreeSplatter 🤗 Gradio Demo
28
  \n\nOfficial demo of the paper [FreeSplatter: Pose-free Gaussian Splatting for Sparse-view 3D Reconstruction](https://arxiv.org/abs/2404.07191). [[Github]](https://github.com/TencentARC/FreeSplatter)
 
70
  with gr.Tabs() as sub_tabs_img_to_3d:
71
  with gr.TabItem('Hunyuan3D Std', id='tab_hunyuan3d_std'):
72
  _, var_img_to_3d_hunyuan3d_std = create_interface_img_to_3d(
73
+ run_img_to_3d,
 
74
  model='Hunyuan3D Std')
75
  with gr.TabItem('Zero123++ v1.1', id='tab_zero123plus_v11'):
76
  _, var_img_to_3d_zero123plus_v11 = create_interface_img_to_3d(
77
+ run_img_to_3d,
 
78
  model='Zero123++ v1.1')
79
  with gr.TabItem('Zero123++ v1.2', id='tab_zero123plus_v12'):
80
  _, var_img_to_3d_zero123plus_v12 = create_interface_img_to_3d(
81
+ run_img_to_3d,
 
82
  model='Zero123++ v1.2')
83
 
84
  gr.Markdown(_CITE_)
freesplatter/webui/runner.py CHANGED
@@ -1,4 +1,3 @@
1
- import spaces
2
  import os
3
  import json
4
  import uuid
@@ -157,17 +156,14 @@ class FreeSplatterRunner:
157
  image,
158
  do_rembg=True,
159
  ):
160
- torch.cuda.empty_cache()
161
-
162
  if do_rembg:
163
  image = remove_background(image, self.rembg)
164
 
165
  return image
166
 
167
- @spaces.GPU
168
  def run_img_to_3d(
169
  self,
170
- image_rgba,
171
  model='Zero123++ v1.2',
172
  diffusion_steps=30,
173
  guidance_scale=4.0,
@@ -177,7 +173,10 @@ class FreeSplatterRunner:
177
  mesh_reduction=0.5,
178
  cache_dir=None,
179
  ):
180
- torch.cuda.empty_cache()
 
 
 
181
 
182
  self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')
183
  os.makedirs(self.output_dir, exist_ok=True)
@@ -226,6 +225,10 @@ class FreeSplatterRunner:
226
  images = images[[0, 2, 4, 5, 3, 1]]
227
  alphas = alphas[[0, 2, 4, 5, 3, 1]]
228
  images_vis = v2.functional.to_pil_image(rearrange(images, 'nm c h w -> c h (nm w)'))
 
 
 
 
229
  images = v2.functional.resize(images, 512, interpolation=3, antialias=True).clamp(0, 1)
230
  alphas = v2.functional.resize(alphas, 512, interpolation=0, antialias=True).clamp(0, 1)
231
 
@@ -237,12 +240,12 @@ class FreeSplatterRunner:
237
  images, alphas = images[view_indices], alphas[view_indices]
238
  legends = [f'V{i}' if i != 0 else 'Input' for i in view_indices]
239
 
240
- gs_vis_path, video_path, mesh_fine_path, fig = self.run_freesplatter_object(
241
- images, alphas, legends=legends, gs_type=gs_type, mesh_reduction=mesh_reduction)
 
 
242
 
243
- return images_vis, gs_vis_path, video_path, mesh_fine_path, fig
244
 
245
- @spaces.GPU
246
  def run_views_to_3d(
247
  self,
248
  image_files,
@@ -251,7 +254,6 @@ class FreeSplatterRunner:
251
  mesh_reduction=0.5,
252
  cache_dir=None,
253
  ):
254
- torch.cuda.empty_cache()
255
 
256
  self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')
257
  os.makedirs(self.output_dir, exist_ok=True)
@@ -300,7 +302,6 @@ class FreeSplatterRunner:
300
  gs_type='2DGS',
301
  mesh_reduction=0.5,
302
  ):
303
- torch.cuda.empty_cache()
304
  device = self.device
305
 
306
  freesplatter = self.freesplatter_2dgs if gs_type == '2DGS' else self.freesplatter
@@ -316,11 +317,13 @@ class FreeSplatterRunner:
316
  c2ws_pred, focals_pred = freesplatter.estimate_poses(images, gaussians, masks=alphas, use_first_focal=True, pnp_iter=10)
317
  fig = self.visualize_cameras_object(images, c2ws_pred, focals_pred, legends=legends)
318
  t2 = time.time()
 
319
 
320
  # save gaussians
321
  gs_vis_path = os.path.join(self.output_dir, 'gs_vis.ply')
322
  save_gaussian(gaussians, gs_vis_path, freesplatter, opacity_threshold=5e-3, pad_2dgs_scale=True)
323
  print(f'Save gaussian at {gs_vis_path}')
 
324
 
325
  # render video
326
  with torch.inference_mode():
@@ -339,6 +342,7 @@ class FreeSplatterRunner:
339
  save_video(video_frames, video_path, fps=30)
340
  print(f'Save video at {video_path}')
341
  t3 = time.time()
 
342
 
343
  # extract mesh
344
  with torch.inference_mode():
@@ -454,7 +458,7 @@ class FreeSplatterRunner:
454
  print(f'Generate mesh: {t4-t3:.2f} seconds.')
455
  print(f'Optimize mesh: {t5-t4:.2f} seconds.')
456
 
457
- return gs_vis_path, video_path, mesh_fine_path, fig
458
 
459
  def visualize_cameras_object(
460
  self,
@@ -494,14 +498,12 @@ class FreeSplatterRunner:
494
  return fig
495
 
496
  # FreeSplatter-S
497
- @spaces.GPU
498
  def run_views_to_scene(
499
  self,
500
  image1,
501
  image2,
502
  cache_dir=None,
503
  ):
504
- torch.cuda.empty_cache()
505
 
506
  self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')
507
  os.makedirs(self.output_dir, exist_ok=True)
@@ -531,7 +533,6 @@ class FreeSplatterRunner:
531
  images,
532
  legends=None,
533
  ):
534
- torch.cuda.empty_cache()
535
 
536
  freesplatter = self.freesplatter_scene
537
 
 
 
1
  import os
2
  import json
3
  import uuid
 
156
  image,
157
  do_rembg=True,
158
  ):
 
 
159
  if do_rembg:
160
  image = remove_background(image, self.rembg)
161
 
162
  return image
163
 
 
164
  def run_img_to_3d(
165
  self,
166
+ image,
167
  model='Zero123++ v1.2',
168
  diffusion_steps=30,
169
  guidance_scale=4.0,
 
173
  mesh_reduction=0.5,
174
  cache_dir=None,
175
  ):
176
+ image_rgba = self.run_segmentation(image)
177
+
178
+ res = [image_rgba]
179
+ yield res + [None] * (6 - len(res))
180
 
181
  self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')
182
  os.makedirs(self.output_dir, exist_ok=True)
 
225
  images = images[[0, 2, 4, 5, 3, 1]]
226
  alphas = alphas[[0, 2, 4, 5, 3, 1]]
227
  images_vis = v2.functional.to_pil_image(rearrange(images, 'nm c h w -> c h (nm w)'))
228
+
229
+ res += [images_vis]
230
+ yield res + [None] * (6 - len(res))
231
+
232
  images = v2.functional.resize(images, 512, interpolation=3, antialias=True).clamp(0, 1)
233
  alphas = v2.functional.resize(alphas, 512, interpolation=0, antialias=True).clamp(0, 1)
234
 
 
240
  images, alphas = images[view_indices], alphas[view_indices]
241
  legends = [f'V{i}' if i != 0 else 'Input' for i in view_indices]
242
 
243
+ for item in self.run_freesplatter_object(
244
+ images, alphas, legends=legends, gs_type=gs_type, mesh_reduction=mesh_reduction):
245
+ res += [item]
246
+ yield res + [None] * (6 - len(res))
247
 
 
248
 
 
249
  def run_views_to_3d(
250
  self,
251
  image_files,
 
254
  mesh_reduction=0.5,
255
  cache_dir=None,
256
  ):
 
257
 
258
  self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')
259
  os.makedirs(self.output_dir, exist_ok=True)
 
302
  gs_type='2DGS',
303
  mesh_reduction=0.5,
304
  ):
 
305
  device = self.device
306
 
307
  freesplatter = self.freesplatter_2dgs if gs_type == '2DGS' else self.freesplatter
 
317
  c2ws_pred, focals_pred = freesplatter.estimate_poses(images, gaussians, masks=alphas, use_first_focal=True, pnp_iter=10)
318
  fig = self.visualize_cameras_object(images, c2ws_pred, focals_pred, legends=legends)
319
  t2 = time.time()
320
+ yield fig
321
 
322
  # save gaussians
323
  gs_vis_path = os.path.join(self.output_dir, 'gs_vis.ply')
324
  save_gaussian(gaussians, gs_vis_path, freesplatter, opacity_threshold=5e-3, pad_2dgs_scale=True)
325
  print(f'Save gaussian at {gs_vis_path}')
326
+ yield gs_vis_path
327
 
328
  # render video
329
  with torch.inference_mode():
 
342
  save_video(video_frames, video_path, fps=30)
343
  print(f'Save video at {video_path}')
344
  t3 = time.time()
345
+ yield video_path
346
 
347
  # extract mesh
348
  with torch.inference_mode():
 
458
  print(f'Generate mesh: {t4-t3:.2f} seconds.')
459
  print(f'Optimize mesh: {t5-t4:.2f} seconds.')
460
 
461
+ yield mesh_fine_path
462
 
463
  def visualize_cameras_object(
464
  self,
 
498
  return fig
499
 
500
  # FreeSplatter-S
 
501
  def run_views_to_scene(
502
  self,
503
  image1,
504
  image2,
505
  cache_dir=None,
506
  ):
 
507
 
508
  self.output_dir = os.path.join(cache_dir, f'output_{uuid.uuid4()}')
509
  os.makedirs(self.output_dir, exist_ok=True)
 
533
  images,
534
  legends=None,
535
  ):
 
536
 
537
  freesplatter = self.freesplatter_scene
538
 
freesplatter/webui/tab_img_to_3d.py CHANGED
@@ -5,7 +5,7 @@ from .gradio_custommodel3d import CustomModel3D
5
  from .gradio_customgs import CustomGS
6
 
7
 
8
- def create_interface_img_to_3d(segmentation_api, freesplatter_api, model='Zero123++ v1.2'):
9
  default_views = {
10
  'Zero123++ v1.1': ['Input', 'V2', 'V3', 'V5'],
11
  'Zero123++ v1.2': ['V1', 'V2', 'V3', 'V5', 'V6'],
@@ -137,14 +137,8 @@ def create_interface_img_to_3d(segmentation_api, freesplatter_api, model='Zero12
137
  )
138
 
139
  var_dict['run_btn'].click(
140
- fn=segmentation_api,
141
- inputs=var_dict['in_image'],
142
- outputs=var_dict['fg_image'],
143
- concurrency_id='default_group',
144
- api_name='run_segmentation',
145
- ).success(
146
- fn=partial(freesplatter_api, cache_dir=interface.GRADIO_CACHE),
147
- inputs=[var_dict['fg_image'],
148
  var_dict['model'],
149
  var_dict['diffusion_steps'],
150
  var_dict['guidance_scale'],
@@ -152,7 +146,7 @@ def create_interface_img_to_3d(segmentation_api, freesplatter_api, model='Zero12
152
  var_dict['view_indices'],
153
  var_dict['gs_type'],
154
  var_dict['mesh_reduction']],
155
- outputs=[var_dict['out_multiview'], var_dict['out_gs_vis'], var_dict['out_video'], var_dict['out_mesh'], var_dict['out_pose']],
156
  concurrency_id='default_group',
157
  api_name='run_image_to_3d',
158
  )
 
5
  from .gradio_customgs import CustomGS
6
 
7
 
8
+ def create_interface_img_to_3d(freesplatter_api, model='Zero123++ v1.2'):
9
  default_views = {
10
  'Zero123++ v1.1': ['Input', 'V2', 'V3', 'V5'],
11
  'Zero123++ v1.2': ['V1', 'V2', 'V3', 'V5', 'V6'],
 
137
  )
138
 
139
  var_dict['run_btn'].click(
140
+ fn=freesplatter_api,
141
+ inputs=[var_dict['in_image'],
 
 
 
 
 
 
142
  var_dict['model'],
143
  var_dict['diffusion_steps'],
144
  var_dict['guidance_scale'],
 
146
  var_dict['view_indices'],
147
  var_dict['gs_type'],
148
  var_dict['mesh_reduction']],
149
+ outputs=[var_dict['fg_image'], var_dict['out_multiview'], var_dict['out_pose'], var_dict['out_gs_vis'], var_dict['out_video'], var_dict['out_mesh']],
150
  concurrency_id='default_group',
151
  api_name='run_image_to_3d',
152
  )
open3d_zerogpu_fix.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import fileinput
2
+ import site
3
+ from pathlib import Path
4
+
5
+ with fileinput.FileInput(f'{site.getsitepackages()[0]}/open3d/__init__.py', inplace=True) as file:
6
+ for line in file:
7
+ print(line.replace('_pybind_cuda.open3d_core_cuda_device_count()', '1'), end='')