Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pulsar unified interface update #1369

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 37 additions & 27 deletions pytorch3d/renderer/points/pulsar/unified.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def _extract_intrinsics( # noqa: C901
"The orthographic camera scale must be ((1.0, 1.0, 1.0),). "
f"{kwargs.get('scale_xyz', cameras.scale_xyz)[cloud_idx]}."
)
sensor_width = max_x - min_x
sensor_width = (max_x - min_x) * (self.renderer._renderer.width / self.renderer._renderer.height)
if not sensor_width > 0.0:
raise ValueError(
f"The orthographic camera must have positive size! Is: {sensor_width}." # noqa: B950
Expand All @@ -220,24 +220,25 @@ def _extract_intrinsics( # noqa: C901
focal_length_conf = kwargs.get("focal_length", cameras.focal_length)[
cloud_idx
]
if (
focal_length_conf.numel() == 2
and focal_length_conf[0] * self.renderer._renderer.width
- focal_length_conf[1] * self.renderer._renderer.height
> 1e-5
):
if torch.any(focal_length_conf <= 0.0):
raise ValueError(f"Pulsar requires focal lengths > 0.0. Provided: {focal_length_conf}.")
if cameras.in_ndc():
focal_length_conf *= self.renderer._renderer.height / 2.0
if (focal_length_conf.numel() == 2 and abs(focal_length_conf[0] - focal_length_conf[1]) > 1e-5):
raise ValueError(
"Pulsar only supports a single focal length! "
"Provided: %s." % (str(focal_length_conf))
)
if focal_length_conf.numel() == 2:
sensor_width = 2.0 / focal_length_conf[0]
focal_length_px = focal_length_conf[0]
else:
if focal_length_conf.numel() != 1:
raise ValueError(
"Focal length not parsable: %s." % (str(focal_length_conf))
)
sensor_width = 2.0 / focal_length_conf
focal_length_px = focal_length_conf
focal_length_px /= self.renderer._renderer.width / 2.0
sensor_width = 2.0 / focal_length_px
if "znear" not in kwargs.keys() or "zfar" not in kwargs.keys():
raise ValueError(
"pulsar needs znear and zfar values for "
Expand All @@ -248,16 +249,19 @@ def _extract_intrinsics( # noqa: C901
zfar = kwargs["zfar"][cloud_idx]
principal_point_x = (
kwargs.get("principal_point", cameras.principal_point)[cloud_idx][0]
* 0.5
* self.renderer._renderer.width
)
principal_point_y = (
kwargs.get("principal_point", cameras.principal_point)[cloud_idx][1]
* 0.5
* self.renderer._renderer.height
)
if cameras.in_ndc():
principal_point_x *= 0.5 * self.renderer._renderer.width * (self.renderer._renderer.height / self.renderer._renderer.width)
principal_point_y *= -0.5 * self.renderer._renderer.height
else:
principal_point_x = self.renderer._renderer.width / 2.0 - principal_point_x
principal_point_y -= self.renderer._renderer.height / 2.0
else:
if not isinstance(cameras, PerspectiveCameras):
# This currently means FoVPerspectiveCameras.
# Create a virtual focal length that is closer than znear.
znear = kwargs.get("znear", cameras.znear)[cloud_idx]
zfar = kwargs.get("zfar", cameras.zfar)[cloud_idx]
Expand All @@ -266,7 +270,10 @@ def _extract_intrinsics( # noqa: C901
afov = kwargs.get("fov", cameras.fov)[cloud_idx]
if kwargs.get("degrees", cameras.degrees):
afov *= math.pi / 180.0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@classner This operation shouldn't be in-place I think!
Replacing afov *= math.pi / 180.0 with afov = afov * math.pi / 180.0 fixed issues with my code.
Thanks for this PR by the way!

sensor_width = math.tan(afov / 2.0) * 2.0 * focal_length
aspect_ratio = kwargs.get("aspect_ratio", cameras.aspect_ratio)[cloud_idx]
if aspect_ratio != 1.0:
raise ValueError(f"Pulsar only supports aspect ration 1.0! Provided: {aspect_ratio}.")
sensor_width = math.tan(afov / 2.0) * 2.0 * focal_length * (self.renderer._renderer.width / self.renderer._renderer.height)
if not (
kwargs.get("aspect_ratio", cameras.aspect_ratio)[cloud_idx]
- self.renderer._renderer.width / self.renderer._renderer.height
Expand All @@ -286,10 +293,13 @@ def _extract_intrinsics( # noqa: C901
focal_length_conf = kwargs.get("focal_length", cameras.focal_length)[
cloud_idx
]
if torch.any(focal_length_conf <= 0.0):
raise ValueError(f"Pulsar requires focal lengths > 0.0. Provided: {focal_length_conf}.")
if cameras.in_ndc():
focal_length_conf *= self.renderer._renderer.height / 2.0
if (
focal_length_conf.numel() == 2
and focal_length_conf[0] * self.renderer._renderer.width
- focal_length_conf[1] * self.renderer._renderer.height
and abs(focal_length_conf[0] - focal_length_conf[1])
> 1e-5
):
raise ValueError(
Expand All @@ -312,6 +322,7 @@ def _extract_intrinsics( # noqa: C901
"Focal length not parsable: %s." % (str(focal_length_conf))
)
focal_length_px = focal_length_conf
focal_length_px /= self.renderer._renderer.width / 2.0
focal_length = torch.tensor(
[
znear - 1e-6,
Expand All @@ -322,14 +333,16 @@ def _extract_intrinsics( # noqa: C901
sensor_width = focal_length / focal_length_px * 2.0
principal_point_x = (
kwargs.get("principal_point", cameras.principal_point)[cloud_idx][0]
* 0.5
* self.renderer._renderer.width
)
principal_point_y = (
kwargs.get("principal_point", cameras.principal_point)[cloud_idx][1]
* 0.5
* self.renderer._renderer.height
)
if cameras.in_ndc():
principal_point_x *= 0.5 * self.renderer._renderer.width * (self.renderer._renderer.height / self.renderer._renderer.width)
principal_point_y *= -0.5 * self.renderer._renderer.height
else:
principal_point_x = self.renderer._renderer.width / 2.0 - principal_point_x
principal_point_y -= self.renderer._renderer.height / 2.0
focal_length = _ensure_float_tensor(focal_length, device)
sensor_width = _ensure_float_tensor(sensor_width, device)
principal_point_x = _ensure_float_tensor(principal_point_x, device)
Expand Down Expand Up @@ -373,7 +386,7 @@ def _extract_extrinsics(
return cam_pos, cam_rot

def _get_vert_rad(
self, vert_pos, cam_pos, orthogonal_projection, focal_length, kwargs, cloud_idx
self, vert_pos, cam_pos, orthogonal_projection, focal_length, sensor_width, kwargs, cloud_idx
) -> torch.Tensor:
"""
Get point radiuses.
Expand Down Expand Up @@ -403,12 +416,8 @@ def _get_vert_rad(
)
else:
point_dists = torch.norm((vert_pos - cam_pos), p=2, dim=1, keepdim=False)
vert_rad = raster_rad / focal_length.to(vert_pos.device) * point_dists
if isinstance(self.rasterizer.cameras, PerspectiveCameras):
# NDC normalization happens through adjusted focal length.
pass
else:
vert_rad = vert_rad / 2.0 # NDC normalization.
vert_rad = raster_rad / focal_length.to(vert_pos.device) * point_dists * sensor_width
vert_rad = vert_rad / 2.0 # NDC normalization.
return vert_rad

# point_clouds is not typed to avoid a cyclic dependency.
Expand Down Expand Up @@ -503,6 +512,7 @@ def forward(self, point_clouds, **kwargs) -> torch.Tensor:
cam_pos,
orthogonal_projection,
focal_length,
sensor_width,
kwargs,
cloud_idx,
)
Expand Down