()
| 317 | |
| 318 | |
| 319 | def main(): |
| 320 | parser = argparse.ArgumentParser(description="Reconstruct a mesh from a point cloud with normals using TSDF.") |
| 321 | parser.add_argument("-i", "--input", type=str, required=True, help="Path to input PLY file") |
| 322 | parser.add_argument("-o", "--output", type=str, default="mesh.ply", help="Path to output PLY file") |
| 323 | parser.add_argument("-x", "--voxel_size", type=float, default=0.0, help="Voxel size (0 for auto-estimation)") |
| 324 | parser.add_argument("-t", "--truncation_mult", type=float, default=3.0, help="Truncation multiplier (default: 3.0)") |
| 325 | parser.add_argument("-c", "--chunk_size", type=int, default=100000, help="Chunk size for vectorized processing (default: 10000)") |
| 326 | parser.add_argument("--method", type=str, choices=["splatting", "voxel"], default="splatting", help="Method: 'splatting' (sparse, faster) or 'voxel' (dense, KDTree)") |
| 327 | |
| 328 | args = parser.parse_args() |
| 329 | |
| 330 | if not os.path.exists(args.input): |
| 331 | print(f"Error: {args.input} not found.") |
| 332 | return |
| 333 | |
| 334 | print(f"Loading {args.input}...") |
| 335 | try: |
| 336 | points, normals = load_ply(args.input) |
| 337 | except Exception as e: |
| 338 | print(f"Error loading points: {e}") |
| 339 | return |
| 340 | print(f"Loaded {len(points)} points.") |
| 341 | |
| 342 | if args.method == "voxel": |
| 343 | # Check for scipy |
| 344 | try: |
| 345 | import scipy |
| 346 | except ImportError: |
| 347 | print("Error: 'voxel' method requires 'scipy'. Please install it: pip install scipy") |
| 348 | return |
| 349 | sdf_grid, min_bound, vs = compute_tsdf_voxel(points, normals, args.voxel_size, args.truncation_mult, args.chunk_size) |
| 350 | extract_mesh_dense(sdf_grid, min_bound, vs, args.output) |
| 351 | else: |
| 352 | tsdf_vol, min_bound, vs = splat_points_to_tsdf(points, normals, args.voxel_size, args.truncation_mult, args.chunk_size) |
| 353 | extract_mesh(tsdf_vol, min_bound, vs, args.output) |
| 354 | |
| 355 | if __name__ == "__main__": |
| 356 | main() |
no test coverage detected