ostapagon commited on
Commit
b46de64
·
1 Parent(s): ada2cc0

Add some instruction. Delete unnesessary ui components.

Browse files
app.py CHANGED
@@ -11,28 +11,25 @@ from gs_demo import gs_demo_tab
11
  torch.backends.cuda.matmul.allow_tf32 = True
12
 
13
  if __name__ == '__main__':
14
- # parser = get_args_parser()
15
- # args = parser.parse_args()
16
-
17
- # if args.server_name is not None:
18
- # server_name = args.server_name
19
- # else:
20
- # server_name = '0.0.0.0'# if args.local_network else '127.0.0.1'
21
-
22
- # weights_path = '/app/wild-gaussian-splatting/mast3r/checkpoints/MASt3R_ViTLarge_BaseDecoder_512_catmlpdpt_metric.pth'
23
- # weights_path = "naver/MASt3R_ViTLarge_BaseDecoder_512_catmlpdpt_metric"#args.weights if args.weights is not None else + MASt3R_ViTLarge_BaseDecoder_512_catmlpdpt_metric
24
- # device = device = 'cuda' if torch.cuda.is_available() else 'cpu'
25
- # chkpt_tag = hash_md5(weights_path)
26
-
27
-
28
  with gr.Blocks() as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  with gr.Tabs():
30
- with gr.Tab("MASt3R Demo"):
31
  mast3r_demo_tab()
32
- with gr.Tab("Gaussian Splatting Demo"):
33
  gs_demo_tab()
34
 
35
- demo.launch(show_error=True, share=None, server_name=None, server_port=None)
36
- # demo.launch(show_error=True, share=None, server_name='0.0.0.0', server_port=5555)
37
-
38
- # python3 demo.py --weights "/app/mast3r/checkpoints/MASt3R_ViTLarge_BaseDecoder_512_catmlpdpt_metric.pth" --device "cuda" --server_port 3334 --local_network "$@"
 
11
  torch.backends.cuda.matmul.allow_tf32 = True
12
 
13
  if __name__ == '__main__':
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  with gr.Blocks() as demo:
15
+ gr.HTML('''
16
+ <div style="text-align: center; padding: 20px; background-color: #f9f9f9; border-radius: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);">
17
+ <h2 style="color: #333;">MASt3R and 3DGS Pipeline Demo</h2>
18
+ <p style="font-size: 16px; color: #555;">This pipeline is designed for 3D reconstruction using MASt3R and 3DGS.</p>
19
+ <p style="font-size: 16px; color: #555;">The process is divided into two stages:</p>
20
+ <ol style="text-align: left; display: inline-block; margin: 0 auto; color: #555;">
21
+ <li>MASt3R is used to obtain the initial point cloud and camera parameters.</li>
22
+ <li>3DGS is then trained on the results from MASt3R to refine the 3D scene representation.</li>
23
+ </ol>
24
+ <p style="font-size: 16px; color: #555;">For a full version of this pipeline, please visit the repository at:</p>
25
+ <a href="https://github.com/nerlfield/wild-gaussian-splatting" target="_blank" style="font-size: 16px; color: #007bff; text-decoration: none;">nerlfield/wild-gaussian-splatting</a>
26
+ </div>
27
+ ''')
28
+
29
  with gr.Tabs():
30
+ with gr.Tab("MASt3R"):
31
  mast3r_demo_tab()
32
+ with gr.Tab("3DGS"):
33
  gs_demo_tab()
34
 
35
+ demo.launch(show_error=True, share=None, server_name=None, server_port=None)
 
 
 
demo/gs_demo.py CHANGED
@@ -30,7 +30,26 @@ def gs_demo_tab():
30
  }
31
  </style>
32
  """)
33
- gr.Markdown("# Gaussian Splatting Training Demo")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
  refresh_button = gr.Button("Refresh Datasets", elem_classes="refresh-button")
36
  dataset_dropdown = gr.Dropdown(label="Select Dataset", choices=[], value="")
@@ -47,33 +66,15 @@ def gs_demo_tab():
47
 
48
  # Set the update function to be called when the refresh button is clicked
49
  refresh_button.click(fn=update_dataset_dropdown, inputs=None, outputs=dataset_dropdown)
50
-
51
- with gr.Accordion("Model Parameters", open=False):
52
- with gr.Row():
53
- with gr.Column():
54
- sh_degree = gr.Number(label="SH Degree", value=3)
55
- model_path = gr.Textbox(label="Model Path", value="")
56
- images = gr.Textbox(label="Images", value="images")
57
- resolution = gr.Number(label="Resolution", value=-1)
58
- white_background = gr.Checkbox(label="White Background", value=True)
59
- data_device = gr.Dropdown(label="Data Device", choices=["cuda", "cpu"], value="cuda")
60
- eval = gr.Checkbox(label="Eval", value=False)
61
-
62
- with gr.Accordion("Pipeline Parameters", open=False):
63
- with gr.Row():
64
- with gr.Column():
65
- convert_SHs_python = gr.Checkbox(label="Convert SHs Python", value=False)
66
- compute_cov3D_python = gr.Checkbox(label="Compute Cov3D Python", value=False)
67
- debug = gr.Checkbox(label="Debug", value=False)
68
 
69
  with gr.Accordion("Optimization Parameters", open=False):
70
  with gr.Row():
71
  with gr.Column():
72
- iterations = gr.Number(label="Iterations", value=1000)
73
- position_lr_init = gr.Number(label="Position LR Init", value=0.00016)
74
- position_lr_final = gr.Number(label="Position LR Final", value=0.0000016)
75
- position_lr_delay_mult = gr.Number(label="Position LR Delay Mult", value=0.01)
76
- position_lr_max_steps = gr.Number(label="Position LR Max Steps", value=30000)
77
  with gr.Column():
78
  feature_lr = gr.Number(label="Feature LR", value=0.0025)
79
  opacity_lr = gr.Number(label="Opacity LR", value=0.05)
@@ -87,7 +88,7 @@ def gs_demo_tab():
87
  densify_from_iter = gr.Number(label="Densify From Iter", value=500)
88
  densify_until_iter = gr.Number(label="Densify Until Iter", value=15000)
89
  densify_grad_threshold = gr.Number(label="Densify Grad Threshold", value=0.0002)
90
- random_background = gr.Checkbox(label="Random Background", value=False)
91
 
92
  start_button = gr.Button("Start Training")
93
 
@@ -129,12 +130,10 @@ def gs_demo_tab():
129
  start_button.click(
130
  fn=handle_training_complete,
131
  inputs=[
132
- dataset_dropdown, sh_degree, model_path, images, resolution, white_background, data_device, eval,
133
- convert_SHs_python, compute_cov3D_python, debug,
134
- iterations, position_lr_init, position_lr_final, position_lr_delay_mult,
135
  position_lr_max_steps, feature_lr, opacity_lr, scaling_lr, rotation_lr,
136
  percent_dense, lambda_dssim, densification_interval, opacity_reset_interval,
137
- densify_from_iter, densify_until_iter, densify_grad_threshold, random_background
138
  ],
139
  outputs=[video_output, load_model_button, output, model_path_state]
140
  )
 
30
  }
31
  </style>
32
  """)
33
+
34
+ # Centered title
35
+ gr.Markdown("""
36
+ <h2 style="text-align: center;">3D Gaussian Splatting Reconstruction</h2>
37
+ """)
38
+
39
+ # Instructions
40
+ gr.Markdown('''
41
+ <div style="padding: 10px; background-color: #e9f7ef; border-radius: 5px; margin-bottom: 10px;">
42
+ <h3>Instructions for 3DGS Demo</h3>
43
+ <ul style="text-align: left; color: #333;">
44
+ <li>Make sure to press "Refresh Datasets" to obtain an updated list of datasets from Stage 1. They are in the format run_0, run_1, run_...</li>
45
+ <li>Adjust optimization parameters if needed, and press "Start Training".</li>
46
+ <li>It is recommended to use 7k iterations to avoid exceeding the 3-minute limit. If you still exceed the limit, reduce the number of iterations.</li>
47
+ <li>After reconstruction is finished, you can view it as a small video generated or download the full 3DGS reconstruction below the video.</li>
48
+ <li>Press "Load 3D Model" to view the full 3DGS reconstruction.</li>
49
+ </ul>
50
+ <p><b>Note: 3DGS '.ply' models could be heavy, so it may take some time to download and view them in the 3D model section.</b></p>
51
+ </div>
52
+ ''')
53
 
54
  refresh_button = gr.Button("Refresh Datasets", elem_classes="refresh-button")
55
  dataset_dropdown = gr.Dropdown(label="Select Dataset", choices=[], value="")
 
66
 
67
  # Set the update function to be called when the refresh button is clicked
68
  refresh_button.click(fn=update_dataset_dropdown, inputs=None, outputs=dataset_dropdown)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
  with gr.Accordion("Optimization Parameters", open=False):
71
  with gr.Row():
72
  with gr.Column():
73
+ position_lr_init = gr.Number(label="Position LR Init", value=0.00032)
74
+ position_lr_final = gr.Number(label="Position LR Final", value=0.0000032)
75
+ position_lr_delay_mult = gr.Number(label="Position LR Delay Mult", value=0.02)
76
+ position_lr_max_steps = gr.Number(label="Position LR Max Steps", value=15000)
77
+ feature_lr = gr.Number(label="Feature LR", value=0.005)
78
  with gr.Column():
79
  feature_lr = gr.Number(label="Feature LR", value=0.0025)
80
  opacity_lr = gr.Number(label="Opacity LR", value=0.05)
 
88
  densify_from_iter = gr.Number(label="Densify From Iter", value=500)
89
  densify_until_iter = gr.Number(label="Densify Until Iter", value=15000)
90
  densify_grad_threshold = gr.Number(label="Densify Grad Threshold", value=0.0002)
91
+ iterations = gr.Slider(label="Iterations", value=7000, minimum=1, maximum=15000, step=5)
92
 
93
  start_button = gr.Button("Start Training")
94
 
 
130
  start_button.click(
131
  fn=handle_training_complete,
132
  inputs=[
133
+ dataset_dropdown, iterations, position_lr_init, position_lr_final, position_lr_delay_mult,
 
 
134
  position_lr_max_steps, feature_lr, opacity_lr, scaling_lr, rotation_lr,
135
  percent_dense, lambda_dssim, densification_interval, opacity_reset_interval,
136
+ densify_from_iter, densify_until_iter, densify_grad_threshold
137
  ],
138
  outputs=[video_output, load_model_button, output, model_path_state]
139
  )
demo/gs_train.py CHANGED
@@ -21,7 +21,8 @@ class PipelineParams:
21
 
22
  @dataclass
23
  class OptimizationParams:
24
- iterations: int = 7000
 
25
  position_lr_init: float = 0.00016
26
  position_lr_final: float = 0.0000016
27
  position_lr_delay_mult: float = 0.01
@@ -50,26 +51,12 @@ class ModelParams:
50
  data_device: str = "cuda"
51
  eval: bool = False
52
 
53
- @dataclass
54
- class TrainingArgs:
55
- ip: str = "0.0.0.0"
56
- port: int = 6007
57
- debug_from: int = -1
58
- detect_anomaly: bool = False
59
- test_iterations: list[int] = field(default_factory=lambda: [7_000, 30_000])
60
- save_iterations: list[int] = field(default_factory=lambda: [7_000, 30_000])
61
- quiet: bool = False
62
- checkpoint_iterations: list[int] = field(default_factory=lambda: [7_000, 15_000, 30_000])
63
- start_checkpoint: str = None
64
-
65
  @spaces.GPU(duration=20)
66
  def train(
67
- data_source_path, sh_degree, model_path, images, resolution, white_background, data_device, eval,
68
- convert_SHs_python, compute_cov3D_python, debug,
69
- iterations, position_lr_init, position_lr_final, position_lr_delay_mult,
70
  position_lr_max_steps, feature_lr, opacity_lr, scaling_lr, rotation_lr,
71
  percent_dense, lambda_dssim, densification_interval, opacity_reset_interval,
72
- densify_from_iter, densify_until_iter, densify_grad_threshold, random_background
73
  ):
74
 
75
  # Add the path to the gaussian-splatting repository
@@ -96,22 +83,9 @@ def train(
96
 
97
  print(data_source_path)
98
  # Create instances of the parameter dataclasses
99
- dataset = ModelParams(
100
- sh_degree=sh_degree,
101
- source_path=data_source_path,
102
- model_path=model_path,
103
- images=images,
104
- resolution=resolution,
105
- white_background=white_background,
106
- data_device=data_device,
107
- eval=eval
108
- )
109
 
110
- pipe = PipelineParams(
111
- convert_SHs_python=convert_SHs_python,
112
- compute_cov3D_python=compute_cov3D_python,
113
- debug=debug
114
- )
115
 
116
  opt = OptimizationParams(
117
  iterations=iterations,
@@ -130,20 +104,7 @@ def train(
130
  densify_from_iter=densify_from_iter,
131
  densify_until_iter=densify_until_iter,
132
  densify_grad_threshold=densify_grad_threshold,
133
- random_background=random_background
134
- )
135
-
136
- print("local_renderer")
137
-
138
- args = TrainingArgs()
139
-
140
- testing_iterations = args.test_iterations
141
- saving_iterations = args.save_iterations
142
- checkpoint_iterations = args.checkpoint_iterations
143
- debug_from = args.debug_from
144
-
145
- tb_writer = prepare_output_and_logger(dataset)
146
-
147
  gaussians = GaussianModel(dataset.sh_degree)
148
  scene = Scene(dataset, gaussians)
149
  gaussians.training_setup(opt)
@@ -175,9 +136,6 @@ def train(
175
  viewpoint_stack = scene.getTrainCameras().copy()
176
  viewpoint_cam = viewpoint_stack.pop(randint(0, len(viewpoint_stack)-1))
177
 
178
- # Render
179
- if (iteration - 1) == debug_from:
180
- pipe.debug = True
181
  bg = torch.rand((3), device=DEVICE) if opt.random_background else background
182
 
183
  render_pkg = render(viewpoint_cam, gaussians, pipe, bg)
@@ -201,7 +159,6 @@ def train(
201
  progress_bar.close()
202
 
203
  # Log and save
204
- training_report(tb_writer, iteration, Ll1, loss, l1_loss, iter_start.elapsed_time(iter_end), testing_iterations, scene, render, (pipe, background))
205
  if (iteration == opt.iterations):
206
  point_cloud_path = os.path.join(os.path.join(dataset.model_path, "point_cloud/iteration_{}".format(iteration)), "point_cloud.ply")
207
  print("\n[ITER {}] Saving Gaussians to {}".format(iteration, point_cloud_path))
@@ -225,9 +182,9 @@ def train(
225
  gaussians.optimizer.step()
226
  gaussians.optimizer.zero_grad(set_to_none = True)
227
 
228
- if (iteration == opt.iterations):
229
- print("\n[ITER {}] Saving Checkpoint".format(iteration))
230
- torch.save((gaussians.capture(), iteration), scene.model_path + "/chkpnt" + str(iteration) + ".pth")
231
 
232
 
233
  from os import makedirs
 
21
 
22
  @dataclass
23
  class OptimizationParams:
24
+ # DEFAULT PARAMETERS
25
+ iterations: int = 30_000
26
  position_lr_init: float = 0.00016
27
  position_lr_final: float = 0.0000016
28
  position_lr_delay_mult: float = 0.01
 
51
  data_device: str = "cuda"
52
  eval: bool = False
53
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  @spaces.GPU(duration=20)
55
  def train(
56
+ data_source_path, iterations, position_lr_init, position_lr_final, position_lr_delay_mult,
 
 
57
  position_lr_max_steps, feature_lr, opacity_lr, scaling_lr, rotation_lr,
58
  percent_dense, lambda_dssim, densification_interval, opacity_reset_interval,
59
+ densify_from_iter, densify_until_iter, densify_grad_threshold
60
  ):
61
 
62
  # Add the path to the gaussian-splatting repository
 
83
 
84
  print(data_source_path)
85
  # Create instances of the parameter dataclasses
86
+ dataset = ModelParams(source_path=data_source_path,)
 
 
 
 
 
 
 
 
 
87
 
88
+ pipe = PipelineParams()
 
 
 
 
89
 
90
  opt = OptimizationParams(
91
  iterations=iterations,
 
104
  densify_from_iter=densify_from_iter,
105
  densify_until_iter=densify_until_iter,
106
  densify_grad_threshold=densify_grad_threshold,
107
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  gaussians = GaussianModel(dataset.sh_degree)
109
  scene = Scene(dataset, gaussians)
110
  gaussians.training_setup(opt)
 
136
  viewpoint_stack = scene.getTrainCameras().copy()
137
  viewpoint_cam = viewpoint_stack.pop(randint(0, len(viewpoint_stack)-1))
138
 
 
 
 
139
  bg = torch.rand((3), device=DEVICE) if opt.random_background else background
140
 
141
  render_pkg = render(viewpoint_cam, gaussians, pipe, bg)
 
159
  progress_bar.close()
160
 
161
  # Log and save
 
162
  if (iteration == opt.iterations):
163
  point_cloud_path = os.path.join(os.path.join(dataset.model_path, "point_cloud/iteration_{}".format(iteration)), "point_cloud.ply")
164
  print("\n[ITER {}] Saving Gaussians to {}".format(iteration, point_cloud_path))
 
182
  gaussians.optimizer.step()
183
  gaussians.optimizer.zero_grad(set_to_none = True)
184
 
185
+ # if (iteration == opt.iterations):
186
+ # print("\n[ITER {}] Saving Checkpoint".format(iteration))
187
+ # torch.save((gaussians.capture(), iteration), scene.model_path + "/chkpnt" + str(iteration) + ".pth")
188
 
189
 
190
  from os import makedirs
demo/mast3r_demo.py CHANGED
@@ -33,7 +33,6 @@ import matplotlib.pyplot as pl
33
 
34
  import torch
35
 
36
-
37
  from demo_globals import CACHE_PATH, MODEL, DEVICE, SILENT, DATASET_DIR
38
 
39
  class SparseGAState():
@@ -175,20 +174,38 @@ def save_colmap_scene(scene, save_dir, min_conf_thr=2, clean_depth=False):
175
  return save_path
176
 
177
  @spaces.GPU(duration=10)
178
- def get_reconstructed_scene(image_size, current_scene_state,
179
- filelist, optim_level, lr1, niter1, lr2, niter2, min_conf_thr, matching_conf_thr,
180
- as_pointcloud, mask_sky, clean_depth, transparent_cams, cam_size, scenegraph_type, winsize,
181
- win_cyclic, refid, TSDF_thresh, shared_intrinsics, **kw):
182
  """
183
  from a list of images, run mast3r inference, sparse global aligner.
184
  then run get_3D_model_from_scene
185
  """
 
186
  imgs = load_images(filelist, size=image_size, verbose=not SILENT)
187
  if len(imgs) == 1:
188
  imgs = [imgs[0], copy.deepcopy(imgs[0])]
189
  imgs[1]['idx'] = 1
190
  filelist = [filelist[0], filelist[0] + '_2']
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  scene_graph_params = [scenegraph_type]
193
  if scenegraph_type in ["swin", "logwin"]:
194
  scene_graph_params.append(str(winsize))
@@ -198,8 +215,6 @@ def get_reconstructed_scene(image_size, current_scene_state,
198
  scene_graph_params.append('noncyclic')
199
  scene_graph = '-'.join(scene_graph_params)
200
  pairs = make_pairs(imgs, scene_graph=scene_graph, prefilter=None, symmetrize=True)
201
- if optim_level == 'coarse':
202
- niter2 = 0
203
 
204
  base_cache_dir = os.path.join(CACHE_PATH, 'cache')
205
  os.makedirs(base_cache_dir, exist_ok=True)
@@ -214,7 +229,6 @@ def get_reconstructed_scene(image_size, current_scene_state,
214
  return run_cache_dir
215
 
216
 
217
- ten = torch.zeros((1024)).cuda()
218
  cache_dir = get_next_dir(base_cache_dir)
219
  scene = sparse_global_alignment(filelist, pairs, cache_dir,
220
  MODEL, lr1=lr1, niter1=niter1, lr2=lr2, niter2=niter2, device=DEVICE,
@@ -243,34 +257,7 @@ def get_reconstructed_scene(image_size, current_scene_state,
243
  return scene_state, outfile
244
 
245
 
246
- def set_scenegraph_options(inputfiles, win_cyclic, refid, scenegraph_type):
247
- num_files = len(inputfiles) if inputfiles is not None else 1
248
- show_win_controls = scenegraph_type in ["swin", "logwin"]
249
- show_winsize = scenegraph_type in ["swin", "logwin"]
250
- show_cyclic = scenegraph_type in ["swin", "logwin"]
251
- max_winsize, min_winsize = 1, 1
252
- if scenegraph_type == "swin":
253
- if win_cyclic:
254
- max_winsize = max(1, math.ceil((num_files - 1) / 2))
255
- else:
256
- max_winsize = num_files - 1
257
- elif scenegraph_type == "logwin":
258
- if win_cyclic:
259
- half_size = math.ceil((num_files - 1) / 2)
260
- max_winsize = max(1, math.ceil(math.log(half_size, 2)))
261
- else:
262
- max_winsize = max(1, math.ceil(math.log(num_files, 2)))
263
- winsize = gradio.Slider(label="Scene Graph: Window Size", value=max_winsize,
264
- minimum=min_winsize, maximum=max_winsize, step=1, visible=show_winsize)
265
- win_cyclic = gradio.Checkbox(value=win_cyclic, label="Cyclic sequence", visible=show_cyclic)
266
- win_col = gradio.Column(visible=show_win_controls)
267
- refid = gradio.Slider(label="Scene Graph: Id", value=0, minimum=0,
268
- maximum=num_files - 1, step=1, visible=scenegraph_type == 'oneref')
269
- return win_col, winsize, win_cyclic, refid
270
-
271
-
272
  def mast3r_demo_tab():
273
-
274
  if not SILENT:
275
  print('Outputing stuff in', CACHE_PATH)
276
 
@@ -281,100 +268,44 @@ def mast3r_demo_tab():
281
 
282
  with get_context() as demo:
283
  scene = gradio.State(None)
 
 
284
  gradio.HTML('<h2 style="text-align: center;">MASt3R Demo</h2>')
285
- with gradio.Column():
286
- inputfiles = gradio.File(file_count="multiple")
287
- with gradio.Row():
288
- with gradio.Column():
289
- with gradio.Row():
290
- lr1 = gradio.Slider(label="Coarse LR", value=0.07, minimum=0.01, maximum=0.2, step=0.01)
291
- niter1 = gradio.Number(value=500, precision=0, minimum=0, maximum=10_000,
292
- label="num_iterations", info="For coarse alignment!")
293
- lr2 = gradio.Slider(label="Fine LR", value=0.014, minimum=0.005, maximum=0.05, step=0.001)
294
- niter2 = gradio.Number(value=200, precision=0, minimum=0, maximum=100_000,
295
- label="num_iterations", info="For refinement!")
296
- optim_level = gradio.Dropdown(["coarse", "refine", "refine+depth"],
297
- value='refine+depth', label="OptLevel",
298
- info="Optimization level")
299
- image_size = gradio.Dropdown(choices=[512, 224], label="Image Size", value=512)
300
- with gradio.Row():
301
- matching_conf_thr = gradio.Slider(label="Matching Confidence Thr", value=5.,
302
- minimum=0., maximum=30., step=0.1,
303
- info="Before Fallback to Regr3D!")
304
- shared_intrinsics = gradio.Checkbox(value=False, label="Shared intrinsics",
305
- info="Only optimize one set of intrinsics for all views")
306
- scenegraph_type = gradio.Dropdown([("complete: all possible image pairs", "complete"),
307
- ("swin: sliding window", "swin"),
308
- ("logwin: sliding window with long range", "logwin"),
309
- ("oneref: match one image with all", "oneref")],
310
- value='complete', label="Scenegraph",
311
- info="Define how to make pairs",
312
- interactive=True)
313
- with gradio.Column(visible=False) as win_col:
314
- winsize = gradio.Slider(label="Scene Graph: Window Size", value=1,
315
- minimum=1, maximum=1, step=1)
316
- win_cyclic = gradio.Checkbox(value=False, label="Cyclic sequence")
317
- refid = gradio.Slider(label="Scene Graph: Id", value=0,
318
- minimum=0, maximum=0, step=1, visible=False)
319
- run_btn = gradio.Button("Run")
320
-
321
- with gradio.Row():
322
- min_conf_thr = gradio.Slider(label="min_conf_thr", value=1.5, minimum=0.0, maximum=10, step=0.1)
323
- cam_size = gradio.Slider(label="cam_size", value=0.2, minimum=0.001, maximum=1.0, step=0.001)
324
- TSDF_thresh = gradio.Slider(label="TSDF Threshold", value=0., minimum=0., maximum=1., step=0.01)
325
- with gradio.Row():
326
- as_pointcloud = gradio.Checkbox(value=True, label="As pointcloud")
327
- mask_sky = gradio.Checkbox(value=False, label="Mask sky")
328
- clean_depth = gradio.Checkbox(value=True, label="Clean-up depthmaps")
329
- transparent_cams = gradio.Checkbox(value=False, label="Transparent cameras")
330
-
331
- outmodel = gradio.Model3D()
332
-
333
- scenegraph_type.change(set_scenegraph_options,
334
- inputs=[inputfiles, win_cyclic, refid, scenegraph_type],
335
- outputs=[win_col, winsize, win_cyclic, refid])
336
- inputfiles.change(set_scenegraph_options,
337
- inputs=[inputfiles, win_cyclic, refid, scenegraph_type],
338
- outputs=[win_col, winsize, win_cyclic, refid])
339
- win_cyclic.change(set_scenegraph_options,
340
- inputs=[inputfiles, win_cyclic, refid, scenegraph_type],
341
- outputs=[win_col, winsize, win_cyclic, refid])
342
- run_btn.click(
343
- fn=get_reconstructed_scene,
344
- inputs=[image_size, scene, inputfiles, optim_level, lr1, niter1, lr2, niter2, min_conf_thr, matching_conf_thr,
345
- as_pointcloud, mask_sky, clean_depth, transparent_cams, cam_size, scenegraph_type, winsize,
346
- win_cyclic, refid, TSDF_thresh, shared_intrinsics],
347
- outputs=[scene, outmodel]
348
- )
349
- # min_conf_thr.release(
350
- # fn=get_3D_model_from_scene,
351
- # inputs=[scene, min_conf_thr, as_pointcloud, mask_sky, clean_depth, transparent_cams, cam_size, TSDF_thresh],
352
- # outputs=outmodel
353
- # )
354
- # cam_size.change(fn=get_3D_model_from_scene,
355
- # inputs=[scene, min_conf_thr, as_pointcloud, mask_sky,
356
- # clean_depth, transparent_cams, cam_size, TSDF_thresh],
357
- # outputs=outmodel)
358
- # TSDF_thresh.change(fn=get_3D_model_from_scene,
359
- # inputs=[scene, min_conf_thr, as_pointcloud, mask_sky,
360
- # clean_depth, transparent_cams, cam_size, TSDF_thresh],
361
- # outputs=outmodel)
362
- # as_pointcloud.change(fn=get_3D_model_from_scene,
363
- # inputs=[scene, min_conf_thr, as_pointcloud, mask_sky,
364
- # clean_depth, transparent_cams, cam_size, TSDF_thresh],
365
- # outputs=outmodel)
366
- # mask_sky.change(fn=get_3D_model_from_scene,
367
- # inputs=[scene, min_conf_thr, as_pointcloud, mask_sky,
368
- # clean_depth, transparent_cams, cam_size, TSDF_thresh],
369
- # outputs=outmodel)
370
- # clean_depth.change(fn=get_3D_model_from_scene,
371
- # inputs=[scene, min_conf_thr, as_pointcloud, mask_sky,
372
- # clean_depth, transparent_cams, cam_size, TSDF_thresh],
373
- # outputs=outmodel)
374
- # transparent_cams.change(fn=get_3D_model_from_scene,
375
- # inputs=[scene, min_conf_thr, as_pointcloud, mask_sky,
376
- # clean_depth, transparent_cams, cam_size, TSDF_thresh],
377
- # outputs=outmodel)
378
 
379
  return demo
380
 
 
33
 
34
  import torch
35
 
 
36
  from demo_globals import CACHE_PATH, MODEL, DEVICE, SILENT, DATASET_DIR
37
 
38
  class SparseGAState():
 
174
  return save_path
175
 
176
  @spaces.GPU(duration=10)
177
+ def get_reconstructed_scene(current_scene_state,
178
+ filelist, min_conf_thr, matching_conf_thr,
179
+ as_pointcloud, cam_size, shared_intrinsics, **kw):
 
180
  """
181
  from a list of images, run mast3r inference, sparse global aligner.
182
  then run get_3D_model_from_scene
183
  """
184
+ image_size = 512
185
  imgs = load_images(filelist, size=image_size, verbose=not SILENT)
186
  if len(imgs) == 1:
187
  imgs = [imgs[0], copy.deepcopy(imgs[0])]
188
  imgs[1]['idx'] = 1
189
  filelist = [filelist[0], filelist[0] + '_2']
190
 
191
+ lr1 = 0.07
192
+ niter1 = 500
193
+ lr2 = 0.014
194
+ niter2 = 200
195
+ optim_level = 'refine'
196
+ mask_sky, clean_depth, transparent_cams = False, True, False
197
+ if len(filelist) < 13:
198
+ scenegraph_type = 'complete'
199
+ winsize = 1
200
+ else:
201
+ scenegraph_type = 'logwin'
202
+ half_size = math.ceil((len(filelist) - 1) / 2)
203
+ max_winsize = max(1, math.ceil(math.log(half_size, 2)))
204
+ winsize = min(5, max_winsize)
205
+ refid = 0
206
+ win_cyclic = False
207
+ TSDF_thresh = 0
208
+
209
  scene_graph_params = [scenegraph_type]
210
  if scenegraph_type in ["swin", "logwin"]:
211
  scene_graph_params.append(str(winsize))
 
215
  scene_graph_params.append('noncyclic')
216
  scene_graph = '-'.join(scene_graph_params)
217
  pairs = make_pairs(imgs, scene_graph=scene_graph, prefilter=None, symmetrize=True)
 
 
218
 
219
  base_cache_dir = os.path.join(CACHE_PATH, 'cache')
220
  os.makedirs(base_cache_dir, exist_ok=True)
 
229
  return run_cache_dir
230
 
231
 
 
232
  cache_dir = get_next_dir(base_cache_dir)
233
  scene = sparse_global_alignment(filelist, pairs, cache_dir,
234
  MODEL, lr1=lr1, niter1=niter1, lr2=lr2, niter2=niter2, device=DEVICE,
 
257
  return scene_state, outfile
258
 
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  def mast3r_demo_tab():
 
261
  if not SILENT:
262
  print('Outputing stuff in', CACHE_PATH)
263
 
 
268
 
269
  with get_context() as demo:
270
  scene = gradio.State(None)
271
+
272
+ # Title for the MASt3R demo
273
  gradio.HTML('<h2 style="text-align: center;">MASt3R Demo</h2>')
274
+
275
+ # Add instructions for the MASt3R demo
276
+ gradio.HTML('''
277
+ <div style="padding: 10px; background-color: #e9f7ef; border-radius: 5px; margin-bottom: 10px;">
278
+ <h3>Instructions for MASt3R Demo</h3>
279
+ <ul style="text-align: left; color: #333;">
280
+ <li>Upload images. It is recommended to use no more than 10-12 images to avoid exceeding the 3-minute runtime limit for zeroGPU dynamic resources.</li>
281
+ <li>Press the "Run" button to start the process.</li>
282
+ <li>Once the stage is finished and the point cloud with cameras is visible below, switch to the 3DGS tab and follow the instructions there.</li>
283
+ </ul>
284
+ </div>
285
+ ''')
286
+
287
+ inputfiles = gradio.File(file_count="multiple")
288
+
289
+ run_btn = gradio.Button("Run")
290
+
291
+ with gradio.Row():
292
+ matching_conf_thr = gradio.Slider(label="Matching Confidence Thr", value=5.,
293
+ minimum=0., maximum=30., step=0.1,
294
+ info="Before Fallback to Regr3D!")
295
+ min_conf_thr = gradio.Slider(label="min_conf_thr", value=1.5, minimum=0.0, maximum=10, step=0.1)
296
+ cam_size = gradio.Slider(label="cam_size", value=0.2, minimum=0.001, maximum=1.0, step=0.001)
297
+ with gradio.Row():
298
+ as_pointcloud = gradio.Checkbox(value=True, label="As pointcloud")
299
+ shared_intrinsics = gradio.Checkbox(value=False, label="Shared intrinsics",
300
+ info="Only optimize one set of intrinsics for all views")
301
+
302
+ outmodel = gradio.Model3D()
303
+ run_btn.click(
304
+ fn=get_reconstructed_scene,
305
+ inputs=[scene, inputfiles, min_conf_thr, matching_conf_thr,
306
+ as_pointcloud, cam_size, shared_intrinsics],
307
+ outputs=[scene, outmodel]
308
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
 
310
  return demo
311
 
requirements.txt CHANGED
@@ -4,6 +4,10 @@
4
  torch==2.4.0
5
  torchvision==0.19.0
6
 
 
 
 
 
7
  gradio
8
  matplotlib
9
  tqdm
@@ -28,8 +32,4 @@ pytorch-lightning==2.1.0
28
  PyYAML==6.0.1
29
  ipywidgets
30
  jupyterlab
31
- sql
32
-
33
- https://huggingface.co/spaces/ostapagon/mast3r-3dgs/resolve/main/wheels/simple_knn-0.0.0-cp310-cp310-linux_x86_64.whl?download=true
34
- https://huggingface.co/spaces/JeffreyXiang/TRELLIS/resolve/main/wheels/nvdiffrast-0.3.3-cp310-cp310-linux_x86_64.whl?download=true
35
- https://huggingface.co/spaces/ostapagon/mast3r-3dgs/resolve/main/wheels/diff_gaussian_rasterization-0.0.0-cp310-cp310-linux_x86_64.whl?download=true
 
4
  torch==2.4.0
5
  torchvision==0.19.0
6
 
7
+ https://huggingface.co/spaces/ostapagon/mast3r-3dgs/resolve/main/wheels/simple_knn-0.0.0-cp310-cp310-linux_x86_64.whl?download=true
8
+ https://huggingface.co/spaces/JeffreyXiang/TRELLIS/resolve/main/wheels/nvdiffrast-0.3.3-cp310-cp310-linux_x86_64.whl?download=true
9
+ https://huggingface.co/spaces/ostapagon/mast3r-3dgs/resolve/main/wheels/diff_gaussian_rasterization-0.0.0-cp310-cp310-linux_x86_64.whl?download=true
10
+
11
  gradio
12
  matplotlib
13
  tqdm
 
32
  PyYAML==6.0.1
33
  ipywidgets
34
  jupyterlab
35
+ sql
 
 
 
 
wheels/simple_knn-0.0.0-cp310-cp310-linux_x86_64.whl CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:6da49f22b9fd37ee6ed579a9724670fc54c0514fd418931b486996c0c2ff8748
3
- size 3041144
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bdbf04f4682c8dcd5d28b6c83755be96e46e6f5d5afb85e9cf0a0e49119e092e
3
+ size 3043536