update sparse_ga and expose parameter in demo
Browse files- demo.py +35 -27
- mast3r/cloud_opt/sparse_ga.py +14 -5
demo.py
CHANGED
@@ -116,9 +116,10 @@ def get_3D_model_from_scene(outdir, silent, scene, min_conf_thr=2, as_pointcloud
|
|
116 |
transparent_cams=transparent_cams, cam_size=cam_size, silent=silent)
|
117 |
|
118 |
|
119 |
-
def get_reconstructed_scene(outdir, model, device, silent, image_size, filelist, optim_level, lr1, niter1, lr2, niter2,
|
120 |
-
as_pointcloud, mask_sky, clean_depth, transparent_cams,
|
121 |
-
scenegraph_type, winsize, win_cyclic, refid, TSDF_thresh, shared_intrinsics,
|
|
|
122 |
"""
|
123 |
from a list of images, run mast3r inference, sparse global aligner.
|
124 |
then run get_3D_model_from_scene
|
@@ -143,7 +144,8 @@ def get_reconstructed_scene(outdir, model, device, silent, image_size, filelist,
|
|
143 |
# Sparse GA (forward mast3r -> matching -> 3D optim -> 2D refinement -> triangulation)
|
144 |
scene = sparse_global_alignment(filelist, pairs, os.path.join(outdir, 'cache'),
|
145 |
model, lr1=lr1, niter1=niter1, lr2=lr2, niter2=niter2, device=device,
|
146 |
-
opt_depth='depth' in optim_level, shared_intrinsics=shared_intrinsics,
|
|
|
147 |
outfile = get_3D_model_from_scene(outdir, silent, scene, min_conf_thr, as_pointcloud, mask_sky,
|
148 |
clean_depth, transparent_cams, cam_size, TSDF_thresh)
|
149 |
return scene, outfile
|
@@ -188,27 +190,33 @@ def main_demo(tmpdirname, model, device, image_size, server_name, server_port, s
|
|
188 |
with gradio.Column():
|
189 |
inputfiles = gradio.File(file_count="multiple")
|
190 |
with gradio.Row():
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
212 |
|
213 |
run_btn = gradio.Button("Run")
|
214 |
|
@@ -238,8 +246,8 @@ def main_demo(tmpdirname, model, device, image_size, server_name, server_port, s
|
|
238 |
inputs=[inputfiles, win_cyclic, refid, scenegraph_type],
|
239 |
outputs=[win_col, winsize, win_cyclic, refid])
|
240 |
run_btn.click(fn=recon_fun,
|
241 |
-
inputs=[inputfiles, optim_level, lr1, niter1, lr2, niter2, min_conf_thr,
|
242 |
-
mask_sky, clean_depth, transparent_cams, cam_size,
|
243 |
scenegraph_type, winsize, win_cyclic, refid, TSDF_thresh, shared_intrinsics],
|
244 |
outputs=[scene, outmodel])
|
245 |
min_conf_thr.release(fn=model_from_scene_fun,
|
|
|
116 |
transparent_cams=transparent_cams, cam_size=cam_size, silent=silent)
|
117 |
|
118 |
|
119 |
+
def get_reconstructed_scene(outdir, model, device, silent, image_size, filelist, optim_level, lr1, niter1, lr2, niter2,
|
120 |
+
min_conf_thr, matching_conf_thr, as_pointcloud, mask_sky, clean_depth, transparent_cams,
|
121 |
+
cam_size, scenegraph_type, winsize, win_cyclic, refid, TSDF_thresh, shared_intrinsics,
|
122 |
+
**kw):
|
123 |
"""
|
124 |
from a list of images, run mast3r inference, sparse global aligner.
|
125 |
then run get_3D_model_from_scene
|
|
|
144 |
# Sparse GA (forward mast3r -> matching -> 3D optim -> 2D refinement -> triangulation)
|
145 |
scene = sparse_global_alignment(filelist, pairs, os.path.join(outdir, 'cache'),
|
146 |
model, lr1=lr1, niter1=niter1, lr2=lr2, niter2=niter2, device=device,
|
147 |
+
opt_depth='depth' in optim_level, shared_intrinsics=shared_intrinsics,
|
148 |
+
matching_conf_thr=matching_conf_thr, **kw)
|
149 |
outfile = get_3D_model_from_scene(outdir, silent, scene, min_conf_thr, as_pointcloud, mask_sky,
|
150 |
clean_depth, transparent_cams, cam_size, TSDF_thresh)
|
151 |
return scene, outfile
|
|
|
190 |
with gradio.Column():
|
191 |
inputfiles = gradio.File(file_count="multiple")
|
192 |
with gradio.Row():
|
193 |
+
with gradio.Column():
|
194 |
+
with gradio.Row():
|
195 |
+
lr1 = gradio.Slider(label="Coarse LR", value=0.07, minimum=0.01, maximum=0.2, step=0.01)
|
196 |
+
niter1 = gradio.Number(value=500, precision=0, minimum=0, maximum=10_000,
|
197 |
+
label="num_iterations", info="For coarse alignment!")
|
198 |
+
lr2 = gradio.Slider(label="Fine LR", value=0.014, minimum=0.005, maximum=0.05, step=0.001)
|
199 |
+
niter2 = gradio.Number(value=200, precision=0, minimum=0, maximum=100_000,
|
200 |
+
label="num_iterations", info="For refinement!")
|
201 |
+
optim_level = gradio.Dropdown(["coarse", "refine", "refine+depth"],
|
202 |
+
value='refine', label="OptLevel",
|
203 |
+
info="Optimization level")
|
204 |
+
with gradio.Row():
|
205 |
+
matching_conf_thr = gradio.Slider(label="Matching Confidence Thr", value=5.,
|
206 |
+
minimum=0., maximum=30., step=0.1,
|
207 |
+
info="Before Fallback to Regr3D!")
|
208 |
+
shared_intrinsics = gradio.Checkbox(value=False, label="Shared intrinsics",
|
209 |
+
info="Only optimize one set of intrinsics for all views")
|
210 |
+
scenegraph_type = gradio.Dropdown(["complete", "swin", "logwin", "oneref"],
|
211 |
+
value='complete', label="Scenegraph",
|
212 |
+
info="Define how to make pairs",
|
213 |
+
interactive=True)
|
214 |
+
with gradio.Column(visible=False) as win_col:
|
215 |
+
winsize = gradio.Slider(label="Scene Graph: Window Size", value=1,
|
216 |
+
minimum=1, maximum=1, step=1)
|
217 |
+
win_cyclic = gradio.Checkbox(value=False, label="Cyclic sequence")
|
218 |
+
refid = gradio.Slider(label="Scene Graph: Id", value=0,
|
219 |
+
minimum=0, maximum=0, step=1, visible=False)
|
220 |
|
221 |
run_btn = gradio.Button("Run")
|
222 |
|
|
|
246 |
inputs=[inputfiles, win_cyclic, refid, scenegraph_type],
|
247 |
outputs=[win_col, winsize, win_cyclic, refid])
|
248 |
run_btn.click(fn=recon_fun,
|
249 |
+
inputs=[inputfiles, optim_level, lr1, niter1, lr2, niter2, min_conf_thr, matching_conf_thr,
|
250 |
+
as_pointcloud, mask_sky, clean_depth, transparent_cams, cam_size,
|
251 |
scenegraph_type, winsize, win_cyclic, refid, TSDF_thresh, shared_intrinsics],
|
252 |
outputs=[scene, outmodel])
|
253 |
min_conf_thr.release(fn=model_from_scene_fun,
|
mast3r/cloud_opt/sparse_ga.py
CHANGED
@@ -144,8 +144,8 @@ def sparse_global_alignment(imgs, pairs_in, cache_path, model, subsample=8, desc
|
|
144 |
# tmp_pairs = {(a,b):v for (a,b),v in tmp_pairs.items() if {(a,b),(b,a)} & min_spanning_tree}
|
145 |
|
146 |
# smartly combine all usefull data
|
147 |
-
imsizes, pps, base_focals, core_depth, anchors, corres, corres2d = \
|
148 |
-
condense_data(imgs, tmp_pairs, canonical_views, dtype)
|
149 |
|
150 |
imgs, res_coarse, res_fine = sparse_scene_optimizer(
|
151 |
imgs, subsample, imsizes, pps, base_focals, core_depth, anchors, corres, corres2d, preds_21, canonical_paths, mst,
|
@@ -345,7 +345,7 @@ def sparse_scene_optimizer(imgs, subsample, imsizes, pps, base_focals, core_dept
|
|
345 |
if init[imgs[s.img1]].get('freeze') and init[imgs[s.img2]].get('freeze'):
|
346 |
continue
|
347 |
# fallback to dust3r regression
|
348 |
-
tgt_pts, tgt_confs =
|
349 |
tgt_pts = geotrf(cam2w[s.img2], tgt_pts)
|
350 |
cf_sum += tgt_confs.sum()
|
351 |
loss += tgt_confs @ pix_loss(pts3d[s.img1], tgt_pts)
|
@@ -733,7 +733,7 @@ PairOfSlices = namedtuple(
|
|
733 |
'ImgPair', 'img1, slice1, pix1, anchor_idxs1, img2, slice2, pix2, anchor_idxs2, confs, confs_sum')
|
734 |
|
735 |
|
736 |
-
def condense_data(imgs, tmp_paths, canonical_views, dtype=torch.float32):
|
737 |
# aggregate all data properly
|
738 |
set_imgs = set(imgs)
|
739 |
|
@@ -809,7 +809,16 @@ def condense_data(imgs, tmp_paths, canonical_views, dtype=torch.float32):
|
|
809 |
imsizes = torch.tensor([(W, H) for H, W in shapes], device=pp.device) # (W,H)
|
810 |
principal_points = torch.stack(principal_points)
|
811 |
focals = torch.cat(focals)
|
812 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
813 |
|
814 |
|
815 |
def canonical_view(ptmaps11, confs11, subsample, mode='avg-angle'):
|
|
|
144 |
# tmp_pairs = {(a,b):v for (a,b),v in tmp_pairs.items() if {(a,b),(b,a)} & min_spanning_tree}
|
145 |
|
146 |
# smartly combine all usefull data
|
147 |
+
imsizes, pps, base_focals, core_depth, anchors, corres, corres2d, preds_21 = \
|
148 |
+
condense_data(imgs, tmp_pairs, canonical_views, preds_21, dtype)
|
149 |
|
150 |
imgs, res_coarse, res_fine = sparse_scene_optimizer(
|
151 |
imgs, subsample, imsizes, pps, base_focals, core_depth, anchors, corres, corres2d, preds_21, canonical_paths, mst,
|
|
|
345 |
if init[imgs[s.img1]].get('freeze') and init[imgs[s.img2]].get('freeze'):
|
346 |
continue
|
347 |
# fallback to dust3r regression
|
348 |
+
tgt_pts, tgt_confs = preds_21[imgs[s.img2]][imgs[s.img1]]
|
349 |
tgt_pts = geotrf(cam2w[s.img2], tgt_pts)
|
350 |
cf_sum += tgt_confs.sum()
|
351 |
loss += tgt_confs @ pix_loss(pts3d[s.img1], tgt_pts)
|
|
|
733 |
'ImgPair', 'img1, slice1, pix1, anchor_idxs1, img2, slice2, pix2, anchor_idxs2, confs, confs_sum')
|
734 |
|
735 |
|
736 |
+
def condense_data(imgs, tmp_paths, canonical_views, preds_21, dtype=torch.float32):
|
737 |
# aggregate all data properly
|
738 |
set_imgs = set(imgs)
|
739 |
|
|
|
809 |
imsizes = torch.tensor([(W, H) for H, W in shapes], device=pp.device) # (W,H)
|
810 |
principal_points = torch.stack(principal_points)
|
811 |
focals = torch.cat(focals)
|
812 |
+
|
813 |
+
# Subsample preds_21
|
814 |
+
subsamp_preds_21 = {}
|
815 |
+
for imk, imv in preds_21.items():
|
816 |
+
subsamp_preds_21[imk] = {}
|
817 |
+
for im2k, (pred, conf) in preds_21[imk].items():
|
818 |
+
idxs = img_anchors[imgs.index(im2k)][1]
|
819 |
+
subsamp_preds_21[imk][im2k] = (pred[idxs], conf[idxs]) # anchors subsample
|
820 |
+
|
821 |
+
return imsizes, principal_points, focals, core_depth, img_anchors, corres, corres2d, subsamp_preds_21
|
822 |
|
823 |
|
824 |
def canonical_view(ptmaps11, confs11, subsample, mode='avg-angle'):
|