def mesh_3d(odm_mesh_folder, odm_mesh_ply, filter_point_cloud_path, max_concurrency): if not io.file_exists(odm_mesh_ply): log.ODM_INFO('Writing ODM Mesh file in: %s' % odm_mesh_ply) oct_tree = 10 samples = 1.0 max_vertex = 200000 point_weight = 4 verbose = False mesh.screened_poisson_reconstruction( filter_point_cloud_path, odm_mesh_ply, depth=oct_tree, samples=samples, maxVertexCount=max_vertex, pointWeight=point_weight, threads=max( 1, max_concurrency - 1 ), # poissonrecon can get stuck on some machines if --threads == all cores verbose=verbose) else: log.ODM_WARNING('Found a valid ODM Mesh file in: %s' % odm_mesh_ply)
def process(self, inputs, outputs): # Benchmarking start_time = system.now_raw() log.ODM_INFO('Running ODM Meshing Cell') # get inputs args = inputs.args tree = inputs.tree reconstruction = inputs.reconstruction # define paths and create working directories system.mkdir_p(tree.odm_meshing) # check if we rerun cell or not rerun_cell = (args.rerun is not None and args.rerun == 'odm_meshing') or \ (args.rerun_all) or \ (args.rerun_from is not None and 'odm_meshing' in args.rerun_from) infile = tree.smvs_model if args.fast_orthophoto: infile = os.path.join(tree.opensfm, 'reconstruction.ply') elif args.use_opensfm_dense: infile = tree.opensfm_model # Create full 3D model unless --skip-3dmodel is set if not args.skip_3dmodel: if not io.file_exists(tree.odm_mesh) or rerun_cell: log.ODM_DEBUG('Writing ODM Mesh file in: %s' % tree.odm_mesh) mesh.screened_poisson_reconstruction( infile, tree.odm_mesh, depth=self.params.oct_tree, samples=self.params.samples, maxVertexCount=self.params.max_vertex, pointWeight=self.params.point_weight, threads=self.params.max_concurrency, verbose=self.params.verbose) else: log.ODM_WARNING('Found a valid ODM Mesh file in: %s' % tree.odm_mesh) # Always generate a 2.5D mesh # unless --use-3dmesh is set. if not args.use_3dmesh: if not io.file_exists(tree.odm_25dmesh) or rerun_cell: log.ODM_DEBUG('Writing ODM 2.5D Mesh file in: %s' % tree.odm_25dmesh) dsm_resolution = gsd.cap_resolution( args.orthophoto_resolution, tree.opensfm_reconstruction, ignore_gsd=args.ignore_gsd) / 100.0 # Create reference DSM at half ortho resolution dsm_resolution *= 2 # Sparse point clouds benefits from using # a larger resolution value (more radius interolation, less holes) if args.fast_orthophoto: dsm_resolution *= 2 mesh.create_25dmesh(infile, tree.odm_25dmesh, dsm_resolution=dsm_resolution, depth=self.params.oct_tree, maxVertexCount=self.params.max_vertex, samples=self.params.samples, verbose=self.params.verbose, max_workers=args.max_concurrency) else: log.ODM_WARNING('Found a valid ODM 2.5D Mesh file in: %s' % tree.odm_25dmesh) outputs.reconstruction = reconstruction if args.time: system.benchmark(start_time, tree.benchmarking, 'Meshing') log.ODM_INFO('Running ODM Meshing Cell - Finished') return ecto.OK if args.end_with != 'odm_meshing' else ecto.QUIT
def mesh_3d(args, odm_mesh_folder, odm_mesh_ply, filter_point_cloud_path, max_concurrency, reconstruction, current_path): oct_tree = 10 samples = 1.0 max_vertex = 200000 point_weight = 4 verbose = False args['fast_orthophoto'] = True if args['use_3dmesh']: if not io.file_exists(odm_mesh_ply): log.ODM_INFO('Writing ODM Mesh file in: %s' % odm_mesh_ply) mesh.screened_poisson_reconstruction( filter_point_cloud_path, odm_mesh_ply, depth=oct_tree, samples=samples, maxVertexCount=max_vertex, pointWeight=point_weight, threads=max( 1, max_concurrency - 1 ), # poissonrecon can get stuck on some machines if --threads == all cores verbose=verbose) else: log.ODM_WARNING('Found a valid ODM Mesh file in: %s' % odm_mesh_ply) if not args['use_3dmesh']: if not io.file_exists(odm_mesh_ply): opensfm_reconstruction = io.join_paths(current_path, 'reconstruction.json') reconstruction = reconstruction log.ODM_INFO('Writing ODM 2.5D Mesh file in: %s' % odm_mesh_ply) ortho_resolution = gsd.cap_resolution( args['orthophoto_resolution'], opensfm_reconstruction, ignore_gsd=args['ignore_gsd'], ignore_resolution=not reconstruction.is_georeferenced(), has_gcp=reconstruction.has_gcp()) / 100.0 dsm_multiplier = max( 1.0, gsd.rounded_gsd(opensfm_reconstruction, default_value=4, ndigits=3, ignore_gsd=args['ignore_gsd'])) # A good DSM size depends on the flight altitude. # Flights at low altitude need more details (higher resolution) # Flights at higher altitude benefit from smoother surfaces (lower resolution) dsm_resolution = ortho_resolution * dsm_multiplier dsm_radius = dsm_resolution * math.sqrt(2) # Sparse point clouds benefits from using # a larger radius interolation --> less holes if args['fast_orthophoto']: dsm_radius *= 2 log.ODM_INFO('ODM 2.5D DSM resolution: %s' % dsm_resolution) mesh.create_25dmesh( filter_point_cloud_path, odm_mesh_ply, dsm_radius=dsm_radius, dsm_resolution=dsm_resolution, depth=oct_tree, maxVertexCount=max_vertex, samples=samples, verbose=verbose, available_cores=max_concurrency, method='poisson' if args['fast_orthophoto'] else 'gridded', smooth_dsm=not args['fast_orthophoto']) else: log.ODM_WARNING('Found a valid ODM 2.5D Mesh file in: %s' % odm_mesh_ply)
def process(self, args, outputs): tree = outputs['tree'] reconstruction = outputs['reconstruction'] # define paths and create working directories system.mkdir_p(tree.odm_meshing) # Create full 3D model unless --skip-3dmodel is set if not args.skip_3dmodel: if not io.file_exists(tree.odm_mesh) or self.rerun(): log.ODM_INFO('Writing ODM Mesh file in: %s' % tree.odm_mesh) mesh.screened_poisson_reconstruction( tree.filtered_point_cloud, tree.odm_mesh, depth=self.params.get('oct_tree'), samples=self.params.get('samples'), maxVertexCount=self.params.get('max_vertex'), pointWeight=self.params.get('point_weight'), threads=max( 1, self.params.get('max_concurrency') - 1 ), # poissonrecon can get stuck on some machines if --threads == all cores verbose=self.params.get('verbose')) else: log.ODM_WARNING('Found a valid ODM Mesh file in: %s' % tree.odm_mesh) self.update_progress(50) # Always generate a 2.5D mesh # unless --use-3dmesh is set. if not args.use_3dmesh: if not io.file_exists(tree.odm_25dmesh) or self.rerun(): log.ODM_INFO('Writing ODM 2.5D Mesh file in: %s' % tree.odm_25dmesh) ortho_resolution = gsd.cap_resolution( args.orthophoto_resolution, tree.opensfm_reconstruction, ignore_gsd=args.ignore_gsd, ignore_resolution=(not reconstruction.is_georeferenced()) and args.ignore_gsd, has_gcp=reconstruction.has_gcp()) / 100.0 dsm_multiplier = max( 1.0, gsd.rounded_gsd(tree.opensfm_reconstruction, default_value=4, ndigits=3, ignore_gsd=args.ignore_gsd)) # A good DSM size depends on the flight altitude. # Flights at low altitude need more details (higher resolution) # Flights at higher altitude benefit from smoother surfaces (lower resolution) dsm_resolution = ortho_resolution * dsm_multiplier dsm_radius = dsm_resolution * math.sqrt(2) if args.fast_orthophoto: dsm_radius *= 2 dsm_resolution *= 8 log.ODM_INFO('ODM 2.5D DSM resolution: %s' % dsm_resolution) mesh.create_25dmesh( tree.filtered_point_cloud, tree.odm_25dmesh, dsm_radius=dsm_radius, dsm_resolution=dsm_resolution, depth=self.params.get('oct_tree'), maxVertexCount=self.params.get('max_vertex'), samples=self.params.get('samples'), verbose=self.params.get('verbose'), available_cores=args.max_concurrency, method='poisson' if args.fast_orthophoto else 'gridded', smooth_dsm=True) else: log.ODM_WARNING('Found a valid ODM 2.5D Mesh file in: %s' % tree.odm_25dmesh)
def process(self, inputs, outputs): # Benchmarking start_time = system.now_raw() log.ODM_INFO('Running ODM Meshing Cell') # get inputs args = inputs.args tree = inputs.tree reconstruction = inputs.reconstruction # define paths and create working directories system.mkdir_p(tree.odm_meshing) # check if we rerun cell or not rerun_cell = (args.rerun is not None and args.rerun == 'odm_meshing') or \ (args.rerun_all) or \ (args.rerun_from is not None and 'odm_meshing' in args.rerun_from) infile = tree.smvs_model if args.fast_orthophoto: infile = os.path.join(tree.opensfm, 'reconstruction.ply') elif args.use_opensfm_dense: infile = tree.opensfm_model # Create full 3D model unless --skip-3dmodel is set if not args.skip_3dmodel: if not io.file_exists(tree.odm_mesh) or rerun_cell: log.ODM_DEBUG('Writing ODM Mesh file in: %s' % tree.odm_mesh) mesh.screened_poisson_reconstruction( infile, tree.odm_mesh, depth=self.params.oct_tree, samples=self.params.samples, maxVertexCount=self.params.max_vertex, pointWeight=self.params.point_weight, threads=self.params.max_concurrency, verbose=self.params.verbose) else: log.ODM_WARNING('Found a valid ODM Mesh file in: %s' % tree.odm_mesh) # Always generate a 2.5D mesh # unless --use-3dmesh is set. if not args.use_3dmesh: if not io.file_exists(tree.odm_25dmesh) or rerun_cell: log.ODM_DEBUG('Writing ODM 2.5D Mesh file in: %s' % tree.odm_25dmesh) ortho_resolution = gsd.cap_resolution( args.orthophoto_resolution, tree.opensfm_reconstruction, ignore_gsd=args.ignore_gsd) / 100.0 dsm_multiplier = max( 1.0, gsd.rounded_gsd(tree.opensfm_reconstruction, default_value=4, ndigits=3, ignore_gsd=args.ignore_gsd)) # A good DSM size depends on the flight altitude. # Flights at low altitude need more details (higher resolution) # Flights at higher altitude benefit from smoother surfaces (lower resolution) dsm_resolution = ortho_resolution * dsm_multiplier dsm_radius = dsm_resolution * math.sqrt(2) # Sparse point clouds benefits from using # a larger radius interolation --> less holes if args.fast_orthophoto: dsm_radius *= 2 log.ODM_DEBUG('ODM 2.5D DSM resolution: %s' % dsm_resolution) mesh.create_25dmesh( infile, tree.odm_25dmesh, dsm_radius=dsm_radius, dsm_resolution=dsm_resolution, depth=self.params.oct_tree, maxVertexCount=self.params.max_vertex, samples=self.params.samples, verbose=self.params.verbose, max_workers=args.max_concurrency, method='poisson' if args.fast_orthophoto else 'gridded') else: log.ODM_WARNING('Found a valid ODM 2.5D Mesh file in: %s' % tree.odm_25dmesh) outputs.reconstruction = reconstruction if args.time: system.benchmark(start_time, tree.benchmarking, 'Meshing') log.ODM_INFO('Running ODM Meshing Cell - Finished') return ecto.OK if args.end_with != 'odm_meshing' else ecto.QUIT