alvin888's picture
Upload 1461 files
e2ebf5f verified
import argparse
from sugar.sugar_utils.general_utils import str2bool
from sugar.sugar_trainers.coarse_density import coarse_training_with_density_regularization
from sugar.sugar_trainers.coarse_sdf import coarse_training_with_sdf_regularization
from sugar.sugar_extractors.coarse_mesh import extract_mesh_from_coarse_sugar
from sugar.sugar_trainers.refine import refined_training
from sugar.sugar_extractors.refined_mesh import extract_mesh_and_texture_from_refined_sugar
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dict__ = self
def main(scene_path="data/custom/", checkpoint_path="output/custom/", regularization_type='density', export_uv_textured_mesh=True, export_ply=True, low_poly=True, refinement_time='short'):
# ----- Parser -----
parser = argparse.ArgumentParser(description='Script to optimize a full SuGaR model.')
# Data and vanilla 3DGS checkpoint
parser.add_argument('-s', '--scene_path',
type=str,
help='(Required) path to the scene data to use.')
parser.add_argument('-c', '--checkpoint_path',
type=str,
help='(Required) path to the vanilla 3D Gaussian Splatting Checkpoint to load.')
parser.add_argument('-i', '--iteration_to_load',
type=int, default=7000,
help='iteration to load.')
# Regularization for coarse SuGaR
parser.add_argument('-r', '--regularization_type', type=str,
help='(Required) Type of regularization to use for coarse SuGaR. Can be "sdf" or "density". '
'For reconstructing detailed objects centered in the scene with 360° coverage, "density" provides a better foreground mesh. '
'For a stronger regularization and a better balance between foreground and background, choose "sdf".')
# Extract mesh
parser.add_argument('-l', '--surface_level', type=float, default=0.3,
help='Surface level to extract the mesh at. Default is 0.3')
parser.add_argument('-v', '--n_vertices_in_mesh', type=int, default=1_000_000,
help='Number of vertices in the extracted mesh.')
parser.add_argument('-b', '--bboxmin', type=str, default=None,
help='Min coordinates to use for foreground.')
parser.add_argument('-B', '--bboxmax', type=str, default=None,
help='Max coordinates to use for foreground.')
parser.add_argument('--center_bbox', type=str2bool, default=True,
help='If True, center the bbox. Default is False.')
# Parameters for refined SuGaR
parser.add_argument('-g', '--gaussians_per_triangle', type=int, default=1,
help='Number of gaussians per triangle.')
parser.add_argument('-f', '--refinement_iterations', type=int, default=15_000,
help='Number of refinement iterations.')
# (Optional) Parameters for textured mesh extraction
parser.add_argument('-t', '--export_uv_textured_mesh', type=str2bool, default=True,
help='If True, will export a textured mesh as an .obj file from the refined SuGaR model. '
'Computing a traditional colored UV texture should take less than 10 minutes.')
parser.add_argument('--square_size',
default=10, type=int, help='Size of the square to use for the UV texture.')
parser.add_argument('--postprocess_mesh', type=str2bool, default=False,
help='If True, postprocess the mesh by removing border triangles with low-density. '
'This step takes a few minutes and is not needed in general, as it can also be risky. '
'However, it increases the quality of the mesh in some cases, especially when an object is visible only from one side.')
parser.add_argument('--postprocess_density_threshold', type=float, default=0.1,
help='Threshold to use for postprocessing the mesh.')
parser.add_argument('--postprocess_iterations', type=int, default=5,
help='Number of iterations to use for postprocessing the mesh.')
# (Optional) PLY file export
parser.add_argument('--export_ply', type=str2bool, default=True,
help='If True, export a ply file with the refined 3D Gaussians at the end of the training. '
'This file can be large (+/- 500MB), but is needed for using the dedicated viewer. Default is True.')
# (Optional) Default configurations
parser.add_argument('--low_poly', type=str2bool, default=False,
help='Use standard config for a low poly mesh, with 200k vertices and 6 Gaussians per triangle.')
parser.add_argument('--high_poly', type=str2bool, default=False,
help='Use standard config for a high poly mesh, with 1M vertices and 1 Gaussians per triangle.')
parser.add_argument('--refinement_time', type=str, default=None,
help="Default configs for time to spend on refinement. Can be 'short', 'medium' or 'long'.")
# Evaluation split
parser.add_argument('--eval', type=str2bool, default=True, help='Use eval split.')
# GPU
parser.add_argument('--gpu', type=int, default=0, help='Index of GPU device to use.')
# Parse arguments
args = parser.parse_args()
if args.low_poly:
args.n_vertices_in_mesh = 200_000
args.gaussians_per_triangle = 6
print('Using low poly config.')
if args.high_poly:
args.n_vertices_in_mesh = 1_000_000
args.gaussians_per_triangle = 1
print('Using high poly config.')
if args.refinement_time == 'short':
args.refinement_iterations = 2_000
print('Using short refinement time.')
if args.refinement_time == 'medium':
args.refinement_iterations = 7_000
print('Using medium refinement time.')
if args.refinement_time == 'long':
args.refinement_iterations = 15_000
print('Using long refinement time.')
if args.export_uv_textured_mesh:
print('Will export a UV-textured mesh as an .obj file.')
if args.export_ply:
print('Will export a ply file with the refined 3D Gaussians at the end of the training.')
if scene_path:
args.scene_path = scene_path
if checkpoint_path:
args.checkpoint_path = checkpoint_path
if regularization_type:
args.regularization_type = regularization_type
if export_uv_textured_mesh:
args.export_uv_textured_mesh = export_uv_textured_mesh
if export_ply:
args.export_ply = export_ply
if low_poly:
args.low_poly = low_poly
if refinement_time:
args.refinement_time = refinement_time
# ----- Optimize coarse SuGaR -----
coarse_args = AttrDict({
'checkpoint_path': args.checkpoint_path,
'scene_path': args.scene_path,
'iteration_to_load': args.iteration_to_load,
'output_dir': None,
'eval': args.eval,
'estimation_factor': 0.2,
'normal_factor': 0.2,
'gpu': args.gpu,
})
if args.regularization_type == 'sdf':
coarse_sugar_path = coarse_training_with_sdf_regularization(coarse_args)
elif args.regularization_type == 'density':
coarse_sugar_path = coarse_training_with_density_regularization(coarse_args)
else:
raise ValueError(f'Unknown regularization type: {args.regularization_type}')
# ----- Extract mesh from coarse SuGaR -----
coarse_mesh_args = AttrDict({
'scene_path': args.scene_path,
'checkpoint_path': args.checkpoint_path,
'iteration_to_load': args.iteration_to_load,
'coarse_model_path': coarse_sugar_path,
'surface_level': args.surface_level,
'decimation_target': args.n_vertices_in_mesh,
'mesh_output_dir': None,
'bboxmin': args.bboxmin,
'bboxmax': args.bboxmax,
'center_bbox': args.center_bbox,
'gpu': args.gpu,
'eval': args.eval,
'use_centers_to_extract_mesh': False,
'use_marching_cubes': False,
'use_vanilla_3dgs': False,
})
coarse_mesh_path = extract_mesh_from_coarse_sugar(coarse_mesh_args)[0]
# ----- Refine SuGaR -----
refined_args = AttrDict({
'scene_path': args.scene_path,
'checkpoint_path': args.checkpoint_path,
'mesh_path': coarse_mesh_path,
'output_dir': None,
'iteration_to_load': args.iteration_to_load,
'normal_consistency_factor': 0.1,
'gaussians_per_triangle': args.gaussians_per_triangle,
'n_vertices_in_fg': args.n_vertices_in_mesh,
'refinement_iterations': args.refinement_iterations,
'bboxmin': args.bboxmin,
'bboxmax': args.bboxmax,
'export_ply': args.export_ply,
'eval': args.eval,
'gpu': args.gpu,
})
refined_sugar_path = refined_training(refined_args)
# ----- Extract mesh and texture from refined SuGaR -----
if args.export_uv_textured_mesh:
refined_mesh_args = AttrDict({
'scene_path': args.scene_path,
'iteration_to_load': args.iteration_to_load,
'checkpoint_path': args.checkpoint_path,
'refined_model_path': refined_sugar_path,
'mesh_output_dir': None,
'n_gaussians_per_surface_triangle': args.gaussians_per_triangle,
'square_size': args.square_size,
'eval': args.eval,
'gpu': args.gpu,
'postprocess_mesh': args.postprocess_mesh,
'postprocess_density_threshold': args.postprocess_density_threshold,
'postprocess_iterations': args.postprocess_iterations,
})
refined_mesh_path = extract_mesh_and_texture_from_refined_sugar(refined_mesh_args)
if __name__ == "__main__":
main()