Description
Hi, thank you for this amazing work!
I've been running into some issues with pulsar rendering, and would appreciate your help. I am loading some parameters from calibrated cameras into a PerspectiveCameras
object, and render the scene with both the default PointsRenderer
and the PulsarPointsRenderer
classes. The default renderer works perfectly and the image is calibrated as expected, but I fail to do the same with pulsar, and my rendered scene is empty.
A previous issue seem to address this problem (#772), but doesn't explain how to handle the focal length and principal points in the absence of K
. I've tried to convert them into a 4x4 intrinsics matrix K
(and then follow the advise in #772), but this didn't resolve the issue.
In another attend, I used the pytorch3d.utils.pulsar_from_cameras_projection
function as suggested in #590 and #734, but there doesn't seem to be a direct way to provide the converted parameters to an object of the PulsarPointsRenderer
class. The conversion function outputs translation, rotation, focal length, sensor width, and principal point parameters in pulsar convention, but the PulsarPointsRenderer
forward doesn't use a sensor width as input. Even when omitting sensor width in the forward, pulsar still doesn't render the scene from the desired view. Could you please explain how to use the mentioned camera parameters with pulsar?
Below is a code example in which I first initialise the default point and pulsar renders, then render the scene with the default renderer (no problem here), and finally experiment with different scenarios for pulsar, which all resulted in a fully black and empty render.
# modules
import torch
from pytorch3d.structures import Pointclouds
from pytorch3d.renderer import PerspectiveCameras
from pytorch3d.transforms import rotation_6d_to_matrix
from pytorch3d.utils.camera_conversions import pulsar_from_cameras_projection
from pytorch3d.renderer import (
PointsRasterizationSettings,
PointsRasterizer,
PointsRenderer,
PulsarPointsRenderer,
AlphaCompositor
)
# default synsin point renderer
def point_renderer(cameras, image_size, radius=0.005, points_per_pixel=50):
raster_settings = PointsRasterizationSettings(
image_size=image_size,
radius=radius,
points_per_pixel=points_per_pixel
)
rasterizer = PointsRasterizer(cameras=cameras, raster_settings=raster_settings)
renderer = PointsRenderer(rasterizer=rasterizer, compositor=AlphaCompositor())
return renderer
# pulsar renderer
def pulsar_renderer(cameras, image_size, radius=0.005, points_per_pixel=10):
raster_settings = PointsRasterizationSettings(
image_size=image_size,
radius=radius,
points_per_pixel=points_per_pixel
)
rasterizer = PointsRasterizer(cameras=cameras, raster_settings=raster_settings)
renderer = PulsarPointsRenderer(rasterizer=rasterizer)
return renderer
# given are R, T, focal_length and principal_point parameters
image_size = torch.Tensor( [[1080, 1920]] )
resolution = (540, 960) # also tried with (1080, 1920)
# perspectivce camera for default renderer
cam_default = PerspectiveCameras(focal_length=focal_length, R=R, T=T, principal_point=principal_point, in_ndc=False, image_size=image_size)
# camera conversion
pulsar_cam = pulsar_from_cameras_projection(cam_default, image_size)
pulsarT = pulsar_cam[:, :3]
pulsarR = rotation_6d_to_matrix( pulsar_cam[:, 3:9] )
pulsar_focal_length = pulsar_cam[:, 9]
pulsar_sensor_width = pulsar_cam[:, 10]
pulsar_principal_point = pulsar_cam[:, 11:]
# perspective camera attempts for pulsar renderer
cam_pulsar1 = PerspectiveCameras()
cam_pulsar2 = PerspectiveCameras(focal_length=pulsar_focal_length, R=pulsarR, T=pulsarT, principal_point=pulsar_principal_point, in_ndc=False, image_size=image_size)
cam_pulsar3 = PerspectiveCameras(focal_length=pulsar_focal_length, R=pulsarR, T=pulsarT, principal_point=pulsar_principal_point, in_ndc=True, image_size=image_size)
# xyz and rgb are given position and color tensors
pcl = Pointclouds(points=[xyz], features=[rgb])
# default rendering : no problems, image properly calibrated
default = point_renderer(cam_default, resolution, radius=0.1)
img_default = default(pcl)[0]
# pulsar renderer attempts : problems
pulsar1 = pulsar_renderer(cam_pulsar1, resolution, radius=0.1)
pulsar2 = pulsar_renderer(cam_pulsar2, resolution, radius=0.1)
pulsar3 = pulsar_renderer(cam_pulsar3, resolution, radius=0.1)
# pulsar rendering attempts with pulsar1 renderer
img_pulsar1 = pulsar1(pcl, focal_length=pulsar_focal_length, R=pulsarR, T=pulsarT, principal_point=pulsar_principal_point, gamma=(1e-5,), znear=(0.1,), zfar=(100.0,))[0]
# pulsar rendering attempts with pulsar2 renderer
img_pulsar2 = pulsar2(pcl, focal_length=pulsar_focal_length, gamma=(1e-5,), znear=(0.1,), zfar=(100.0,))[0] # if focal length is not passed, pulsar will complain about single focal length needed
img_pulsar3 = pulsar2(pcl, focal_length=pulsar_focal_length, R=pulsarR, T=pulsarT, principal_point=pulsar_principal_point, gamma=(1e-5,), znear=(0.1,), zfar=(100.0,))[0]
# pulsar rendering attempts with pulsar3 renderer
img_pulsar4 = pulsar3(pcl, focal_length=pulsar_focal_length, gamma=(1e-5,), znear=(0.1,), zfar=(100.0,))[0] # if focal length is not passed, pulsar will complain about single focal length needed
img_pulsar5 = pulsar3(pcl, focal_length=pulsar_focal_length, R=pulsarR, T=pulsarT, principal_point=pulsar_principal_point, gamma=(1e-5,), znear=(0.1,), zfar=(100.0,))[0]
Thank you in advance!