zhaoshiwen's picture
Initial upload: BPN deblur pipeline code (scripts, triangle-splatting, BAGS, EVSSM forks)
c75b162 verified
Raw
History Blame Contribute Delete
5.91 kB
#
# Copyright (C) 2023, Inria
# GRAPHDECO research group, https://team.inria.fr/graphdeco
# All rights reserved.
#
# This software is free for non-commercial, research and evaluation use
# under the terms of the LICENSE.md file.
#
# For inquiries contact george.drettakis@inria.fr
#
from argparse import ArgumentParser, Namespace
import sys
import os
class GroupParams:
pass
class ParamGroup:
def __init__(self, parser: ArgumentParser, name : str, fill_none = False):
group = parser.add_argument_group(name)
for key, value in vars(self).items():
shorthand = False
if key.startswith("_"):
shorthand = True
key = key[1:]
t = type(value)
value = value if not fill_none else None
if shorthand:
if t == bool:
group.add_argument("--" + key, ("-" + key[0:1]), default=value, action="store_true")
else:
group.add_argument("--" + key, ("-" + key[0:1]), default=value, type=t)
else:
if t == bool:
if value is False:
group.add_argument("--" + key, default=value, action="store_true")
else:
group.add_argument("--" + key, default=value, action="store_false")
else:
group.add_argument("--" + key, default=value, type=t)
def extract(self, args):
group = GroupParams()
for arg in vars(args).items():
if arg[0] in vars(self) or ("_" + arg[0]) in vars(self):
setattr(group, arg[0], arg[1])
return group
class ModelParams(ParamGroup):
def __init__(self, parser, sentinel=False):
self.sh_degree = 3
self._source_path = ""
self._model_path = ""
self._images = "images"
self._resolution = -1
self._white_background = False
self.data_device = "cuda"
self.eval = False
self._kernel_size = 0.3 # v2: anti-aliasing (was 0.1)
# self.use_spatial_gaussian_bias = False
self.ray_jitter = False
self.resample_gt_image = False
self.load_allres = False
self.sample_more_highres = False
self.llffhold = 8
print('$$',self._resolution)
self.load_strict = False
self.kernel_size1 = 5
self.kernel_size2 = 9
self.kernel_size3 = 21 # v2: larger blur kernel (17→21, 33 OOMs on 1296×968)
self.kernel_size_ss = 21 # v2: larger blur kernel
super().__init__(parser, "Loading Parameters", sentinel)
def extract(self, args):
g = super().extract(args)
g.source_path = os.path.abspath(g.source_path)
return g
class PipelineParams(ParamGroup):
def __init__(self, parser):
self.convert_SHs_python = False
self.compute_cov3D_python = False
self.debug = False
super().__init__(parser, "Pipeline Parameters")
class OptimizationParams(ParamGroup):
def __init__(self, parser):
self.iterations = 60_000
self.position_lr_init = 0.00016
self.position_lr_final = 0.0000016
self.position_lr_delay_mult = 0.01
self.position_lr_max_steps = 60_000
self.feature_lr = 0.0025
self.opacity_lr = 0.05
self.scaling_lr = 0.005
self.rotation_lr = 0.001
self.percent_dense = 0.01
self.lambda_dssim = 0.2
self.densification_interval = 100
self.opacity_reset_interval = 3000
self.densify_from_iter = 500
self.densify_until_iter = 35_000
self.ms_steps = 6000
self.not_use_rgbd = False
self.not_use_pe = False
self.init_dgt = 0.0006
self.densify_grad_threshold = 0.0002
self.init_opacity = -1.0
self.min_opacity = 0.005
self.no_bpn = False # skip BPN entirely → vanilla MipSplatting
self.use_depth_loss = False # controlled via --use_depth_loss flag (store_true)
self.depth_loss_alpha = 0.01 # v2: tuned alpha
self.use_mask_loss = True
self.mask_loss_alpha = 0.001
self.use_rgbtv_loss = False
self.rgbtv_loss_alpha = 0.001
self.use_another_mlp = False
# BPN's blur-synthesis target (mask*rgb + (1-mask)*render vs RAW input):
# RAW frame cache (load_raw_blurry_cache) + sharp-frame skip set.
self.raw_blurry_glob = ""
self.raw_blurry_stride = 10
self.bpn_skip_sharp_json = ""
# BPN MLP (mlp_rgb_ss/mlp_rgb_ms) param-group lr split by name:
# 'head' params (kernel) -> bpn_lr_kernel, 'mask' params -> bpn_lr_mask,
# everything else (backbone) -> bpn_lr_kernel. Defaults match BAGS'
# native KERLR=5e-4 * lr_scale(ks3=21)~=0.8997 -> ~4.5e-4 for both.
self.bpn_lr_kernel = 4.5e-4
self.bpn_lr_mask = 4.5e-4
# Global cap on total gaussian count (mirrors TriSplat's --max_shapes).
# 0 = disabled (no cap, original BAGS behavior).
self.max_shapes = 0
super().__init__(parser, "Optimization Parameters")
def get_combined_args(parser : ArgumentParser):
cmdlne_string = sys.argv[1:]
cfgfile_string = "Namespace()"
args_cmdline = parser.parse_args(cmdlne_string)
try:
cfgfilepath = os.path.join(args_cmdline.model_path, "cfg_args")
print("Looking for config file in", cfgfilepath)
with open(cfgfilepath) as cfg_file:
print("Config file found: {}".format(cfgfilepath))
cfgfile_string = cfg_file.read()
except TypeError:
print("Config file not found at")
pass
args_cfgfile = eval(cfgfile_string)
merged_dict = vars(args_cfgfile).copy()
for k,v in vars(args_cmdline).items():
if v != None:
merged_dict[k] = v
return Namespace(**merged_dict)