Initial upload: BPN deblur pipeline code (scripts, triangle-splatting, BAGS, EVSSM forks)
c75b162 verified | # | |
| # The original code is under the following copyright: | |
| # 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_GS.md file. | |
| # | |
| # For inquiries contact george.drettakis@inria.fr | |
| # | |
| # The modifications of the code are under the following copyright: | |
| # Copyright (C) 2024, University of Liege, KAUST and University of Oxford | |
| # TELIM research group, http://www.telecom.ulg.ac.be/ | |
| # IVUL research group, https://ivul.kaust.edu.sa/ | |
| # VGG research group, https://www.robots.ox.ac.uk/~vgg/ | |
| # All rights reserved. | |
| # The modifications are under the LICENSE.md file. | |
| # | |
| # For inquiries contact jan.held@uliege.be | |
| # | |
| from typing import NamedTuple | |
| import torch.nn as nn | |
| import torch | |
| from . import _C | |
| def cpu_deep_copy_tuple(input_tuple): | |
| copied_tensors = [item.cpu().clone() if isinstance(item, torch.Tensor) else item for item in input_tuple] | |
| return tuple(copied_tensors) | |
| def rasterize_triangles( | |
| triangles_points, | |
| sigma, | |
| num_points_per_triangle, | |
| cumsum_of_points_per_triangle, | |
| number_of_points, | |
| sh, | |
| colors_precomp, | |
| opacities, | |
| means2D, | |
| scaling, | |
| density_factor, | |
| raster_settings, | |
| ): | |
| return _RasterizeTriangles.apply( | |
| triangles_points, | |
| sigma, | |
| num_points_per_triangle, | |
| cumsum_of_points_per_triangle, | |
| number_of_points, | |
| sh, | |
| colors_precomp, | |
| opacities, | |
| means2D, | |
| scaling, | |
| density_factor, | |
| raster_settings, | |
| ) | |
| class _RasterizeTriangles(torch.autograd.Function): | |
| def forward( | |
| ctx, | |
| triangles_points, | |
| sigma, | |
| num_points_per_triangle, | |
| cumsum_of_points_per_triangle, | |
| number_of_points, | |
| sh, | |
| colors_precomp, | |
| opacities, | |
| means2D, | |
| scaling, | |
| density_factor, | |
| raster_settings, | |
| ): | |
| # Restructure arguments the way that the C++ lib expects them | |
| args = ( | |
| raster_settings.bg, | |
| triangles_points, | |
| sigma, | |
| num_points_per_triangle, | |
| cumsum_of_points_per_triangle, | |
| colors_precomp, | |
| opacities, | |
| scaling, | |
| density_factor, | |
| raster_settings.viewmatrix, | |
| raster_settings.projmatrix, | |
| number_of_points, | |
| raster_settings.tanfovx, | |
| raster_settings.tanfovy, | |
| raster_settings.image_height, | |
| raster_settings.image_width, | |
| sh, | |
| raster_settings.sh_degree, | |
| raster_settings.campos, | |
| raster_settings.prefiltered, | |
| raster_settings.debug | |
| ) | |
| # Invoke C++/CUDA rasterizer | |
| if raster_settings.debug: | |
| cpu_args = cpu_deep_copy_tuple(args) # Copy them before they can be corrupted | |
| try: | |
| num_rendered, color, depth, radii, geomBuffer, binningBuffer, imgBuffer, scaling, density_factor, max_blending = _C.rasterize_triangles(*args) | |
| except Exception as ex: | |
| torch.save(cpu_args, "snapshot_fw.dump") | |
| print("\nAn error occured in forward. Please forward snapshot_fw.dump for debugging.") | |
| raise ex | |
| else: | |
| num_rendered, color, depth, radii, geomBuffer, binningBuffer, imgBuffer, scaling, density_factor, max_blending = _C.rasterize_triangles(*args) | |
| # Keep relevant tensors for backward | |
| ctx.raster_settings = raster_settings | |
| ctx.num_rendered = num_rendered | |
| ctx.number_of_points = number_of_points | |
| ctx.save_for_backward(triangles_points, sigma, num_points_per_triangle, cumsum_of_points_per_triangle, colors_precomp, radii, sh, geomBuffer, binningBuffer, imgBuffer) | |
| return color, radii, scaling, density_factor, depth, max_blending | |
| def backward(ctx, grad_out_color, _, __, ___, grad_depth, _____): | |
| # Restore necessary values from context | |
| num_rendered = ctx.num_rendered | |
| raster_settings = ctx.raster_settings | |
| number_of_points = ctx.number_of_points | |
| triangles_points, sigma, num_points_per_triangle, cumsum_of_points_per_triangle, colors_precomp, radii, sh, geomBuffer, binningBuffer, imgBuffer = ctx.saved_tensors | |
| # Restructure args as C++ method expects them | |
| args = (raster_settings.bg, | |
| triangles_points, | |
| sigma, | |
| num_points_per_triangle, | |
| cumsum_of_points_per_triangle, | |
| radii, | |
| colors_precomp, | |
| raster_settings.viewmatrix, | |
| raster_settings.projmatrix, | |
| number_of_points, | |
| raster_settings.tanfovx, | |
| raster_settings.tanfovy, | |
| grad_out_color, | |
| grad_depth, | |
| sh, | |
| raster_settings.sh_degree, | |
| raster_settings.campos, | |
| geomBuffer, | |
| num_rendered, | |
| binningBuffer, | |
| imgBuffer, | |
| raster_settings.debug) | |
| # Compute gradients for relevant tensors by invoking backward method | |
| if raster_settings.debug: | |
| cpu_args = cpu_deep_copy_tuple(args) # Copy them before they can be corrupted | |
| try: | |
| grad_triangles, grad_sigma, grad_colors_precomp, grad_opacities, grad_sh, grad_means2D = _C.rasterize_triangles_backward(*args) | |
| except Exception as ex: | |
| torch.save(cpu_args, "snapshot_bw.dump") | |
| print("\nAn error occured in backward. Writing snapshot_bw.dump for debugging.\n") | |
| raise ex | |
| else: | |
| grad_triangles, grad_sigma, grad_colors_precomp, grad_opacities, grad_sh, grad_means2D = _C.rasterize_triangles_backward(*args) | |
| #print(torch.max(torch.abs(grad_triangles)), torch.min(torch.abs(grad_triangles))) | |
| #grad_triangles = grad_triangles.reshape(-1, 8, 3) | |
| grad_triangles = grad_triangles.flatten(0) | |
| grad_sigma = grad_sigma.view(-1, 1) | |
| grads = ( | |
| grad_triangles, | |
| grad_sigma, | |
| None, | |
| None, | |
| None, | |
| grad_sh, | |
| grad_colors_precomp, | |
| grad_opacities, | |
| grad_means2D, | |
| None, | |
| None, | |
| None | |
| ) | |
| return grads | |
| class TriangleRasterizationSettings(NamedTuple): | |
| image_height: int | |
| image_width: int | |
| tanfovx : float | |
| tanfovy : float | |
| bg : torch.Tensor | |
| scale_modifier : float | |
| viewmatrix : torch.Tensor | |
| projmatrix : torch.Tensor | |
| sh_degree : int | |
| campos : torch.Tensor | |
| prefiltered : bool | |
| debug : bool | |
| class TriangleRasterizer(nn.Module): | |
| def __init__(self, raster_settings): | |
| super().__init__() | |
| self.raster_settings = raster_settings | |
| def markVisible(self, positions): | |
| # Mark visible points (based on frustum culling for camera) with a boolean | |
| with torch.no_grad(): | |
| raster_settings = self.raster_settings | |
| visible = _C.mark_visible( | |
| positions, | |
| raster_settings.viewmatrix, | |
| raster_settings.projmatrix) | |
| return visible | |
| def forward(self, triangles_points, sigma, num_points_per_triangle, cumsum_of_points_per_triangle, number_of_points, opacities, means2D, scaling, density_factor, shs = None, colors_precomp = None): | |
| raster_settings = self.raster_settings | |
| if (shs is None and colors_precomp is None) or (shs is not None and colors_precomp is not None): | |
| raise Exception('Please provide excatly one of either SHs or precomputed colors!') | |
| if shs is None: | |
| shs = torch.Tensor([]) | |
| if colors_precomp is None: | |
| colors_precomp = torch.Tensor([]) | |
| # Invoke C++/CUDA rasterization routine | |
| return rasterize_triangles( | |
| triangles_points, | |
| sigma, | |
| num_points_per_triangle, | |
| cumsum_of_points_per_triangle, | |
| number_of_points, | |
| shs, | |
| colors_precomp, | |
| opacities, | |
| means2D, | |
| scaling, | |
| density_factor, | |
| raster_settings, | |
| ) | |