mirror of
https://github.com/facebookresearch/pytorch3d.git
synced 2025-08-02 20:02:49 +08:00
Updates to cameras and rasterizer to infer camera type correctly
Summary: Small update to the cameras and rasterizer to correctly infer the type of camera (perspective vs orthographic). Reviewed By: jcjohnson Differential Revision: D26267225 fbshipit-source-id: a58ed3bc2ab25553d2a4307c734204c1d41b5176
This commit is contained in:
parent
39f49c22cd
commit
838b73d3b6
@ -50,7 +50,8 @@ class CamerasBase(TensorProperties):
|
|||||||
- `transform_points` which takes a set of input points in world coordinates and
|
- `transform_points` which takes a set of input points in world coordinates and
|
||||||
projects to NDC coordinates ranging from [-1, -1, znear] to [+1, +1, zfar].
|
projects to NDC coordinates ranging from [-1, -1, znear] to [+1, +1, zfar].
|
||||||
- `transform_points_screen` which takes a set of input points in world coordinates and
|
- `transform_points_screen` which takes a set of input points in world coordinates and
|
||||||
projects them to the screen coordinates ranging from [0, 0, znear] to [W-1, H-1, zfar]
|
projects them to the screen coordinates ranging from
|
||||||
|
[0, 0, znear] to [W-1, H-1, zfar]
|
||||||
|
|
||||||
For each new camera, one should implement the `get_projection_transform`
|
For each new camera, one should implement the `get_projection_transform`
|
||||||
routine that returns the mapping from camera view coordinates to NDC coordinates.
|
routine that returns the mapping from camera view coordinates to NDC coordinates.
|
||||||
@ -268,6 +269,12 @@ class CamerasBase(TensorProperties):
|
|||||||
other = cam_type(device=self.device)
|
other = cam_type(device=self.device)
|
||||||
return super().clone(other)
|
return super().clone(other)
|
||||||
|
|
||||||
|
def is_perspective(self):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def get_znear(self):
|
||||||
|
return self.znear if hasattr(self, "znear") else None
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# Field of View Camera Classes #
|
# Field of View Camera Classes #
|
||||||
@ -534,6 +541,9 @@ class FoVPerspectiveCameras(CamerasBase):
|
|||||||
unprojection_transform = to_ndc_transform.inverse()
|
unprojection_transform = to_ndc_transform.inverse()
|
||||||
return unprojection_transform.transform_points(xy_sdepth)
|
return unprojection_transform.transform_points(xy_sdepth)
|
||||||
|
|
||||||
|
def is_perspective(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def OpenGLOrthographicCameras(
|
def OpenGLOrthographicCameras(
|
||||||
znear=1.0,
|
znear=1.0,
|
||||||
@ -752,6 +762,9 @@ class FoVOrthographicCameras(CamerasBase):
|
|||||||
unprojection_transform = to_ndc_transform.inverse()
|
unprojection_transform = to_ndc_transform.inverse()
|
||||||
return unprojection_transform.transform_points(xy_sdepth)
|
return unprojection_transform.transform_points(xy_sdepth)
|
||||||
|
|
||||||
|
def is_perspective(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# MultiView Camera Classes #
|
# MultiView Camera Classes #
|
||||||
@ -927,6 +940,9 @@ class PerspectiveCameras(CamerasBase):
|
|||||||
)
|
)
|
||||||
return unprojection_transform.transform_points(xy_inv_depth)
|
return unprojection_transform.transform_points(xy_inv_depth)
|
||||||
|
|
||||||
|
def is_perspective(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def SfMOrthographicCameras(
|
def SfMOrthographicCameras(
|
||||||
focal_length=1.0, principal_point=((0.0, 0.0),), R=_R, T=_T, device="cpu"
|
focal_length=1.0, principal_point=((0.0, 0.0),), R=_R, T=_T, device="cpu"
|
||||||
@ -1086,6 +1102,9 @@ class OrthographicCameras(CamerasBase):
|
|||||||
unprojection_transform = to_ndc_transform.inverse()
|
unprojection_transform = to_ndc_transform.inverse()
|
||||||
return unprojection_transform.transform_points(xy_depth)
|
return unprojection_transform.transform_points(xy_depth)
|
||||||
|
|
||||||
|
def is_perspective(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
################################################
|
################################################
|
||||||
# Helper functions for cameras #
|
# Helper functions for cameras #
|
||||||
|
@ -139,8 +139,13 @@ class MeshRasterizer(nn.Module):
|
|||||||
if clip_barycentric_coords is None:
|
if clip_barycentric_coords is None:
|
||||||
clip_barycentric_coords = raster_settings.blur_radius > 0.0
|
clip_barycentric_coords = raster_settings.blur_radius > 0.0
|
||||||
|
|
||||||
# TODO(jcjohns): Should we try to set perspective_correct automatically
|
# If not specified, infer perspective_correct from the camera
|
||||||
# based on the type of the camera?
|
cameras = kwargs.get("cameras", self.cameras)
|
||||||
|
if raster_settings.perspective_correct is not None:
|
||||||
|
perspective_correct = raster_settings.perspective_correct
|
||||||
|
else:
|
||||||
|
perspective_correct = cameras.is_perspective()
|
||||||
|
|
||||||
pix_to_face, zbuf, bary_coords, dists = rasterize_meshes(
|
pix_to_face, zbuf, bary_coords, dists = rasterize_meshes(
|
||||||
meshes_screen,
|
meshes_screen,
|
||||||
image_size=raster_settings.image_size,
|
image_size=raster_settings.image_size,
|
||||||
@ -148,7 +153,7 @@ class MeshRasterizer(nn.Module):
|
|||||||
faces_per_pixel=raster_settings.faces_per_pixel,
|
faces_per_pixel=raster_settings.faces_per_pixel,
|
||||||
bin_size=raster_settings.bin_size,
|
bin_size=raster_settings.bin_size,
|
||||||
max_faces_per_bin=raster_settings.max_faces_per_bin,
|
max_faces_per_bin=raster_settings.max_faces_per_bin,
|
||||||
perspective_correct=raster_settings.perspective_correct,
|
perspective_correct=perspective_correct,
|
||||||
clip_barycentric_coords=clip_barycentric_coords,
|
clip_barycentric_coords=clip_barycentric_coords,
|
||||||
cull_backfaces=raster_settings.cull_backfaces,
|
cull_backfaces=raster_settings.cull_backfaces,
|
||||||
)
|
)
|
||||||
|
@ -794,6 +794,11 @@ class TestFoVPerspectiveProjection(TestCaseMixin, unittest.TestCase):
|
|||||||
new_points = cam.transform_points(points)
|
new_points = cam.transform_points(points)
|
||||||
self.assertClose(new_points, projected_points)
|
self.assertClose(new_points, projected_points)
|
||||||
|
|
||||||
|
def test_perspective_type(self):
|
||||||
|
cam = FoVPerspectiveCameras(znear=1.0, zfar=10.0, fov=60.0)
|
||||||
|
self.assertTrue(cam.is_perspective())
|
||||||
|
self.assertEquals(cam.get_znear(), 1.0)
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# FoVOrthographic Camera #
|
# FoVOrthographic Camera #
|
||||||
@ -885,6 +890,11 @@ class TestFoVOrthographicProjection(TestCaseMixin, unittest.TestCase):
|
|||||||
)
|
)
|
||||||
self.assertClose(scale_grad, grad_scale)
|
self.assertClose(scale_grad, grad_scale)
|
||||||
|
|
||||||
|
def test_perspective_type(self):
|
||||||
|
cam = FoVOrthographicCameras(znear=1.0, zfar=10.0)
|
||||||
|
self.assertFalse(cam.is_perspective())
|
||||||
|
self.assertEquals(cam.get_znear(), 1.0)
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# Orthographic Camera #
|
# Orthographic Camera #
|
||||||
@ -937,6 +947,11 @@ class TestOrthographicProjection(TestCaseMixin, unittest.TestCase):
|
|||||||
v1 = P.transform_points(vertices)
|
v1 = P.transform_points(vertices)
|
||||||
self.assertClose(v1, projected_verts)
|
self.assertClose(v1, projected_verts)
|
||||||
|
|
||||||
|
def test_perspective_type(self):
|
||||||
|
cam = OrthographicCameras(focal_length=5.0, principal_point=((2.5, 2.5),))
|
||||||
|
self.assertFalse(cam.is_perspective())
|
||||||
|
self.assertEquals(cam.get_znear(), None)
|
||||||
|
|
||||||
|
|
||||||
############################################################
|
############################################################
|
||||||
# Perspective Camera #
|
# Perspective Camera #
|
||||||
@ -983,3 +998,8 @@ class TestPerspectiveProjection(TestCaseMixin, unittest.TestCase):
|
|||||||
v1 = P.transform_points(vertices)
|
v1 = P.transform_points(vertices)
|
||||||
v2 = sfm_perspective_project_naive(vertices, fx=2.0, fy=2.0, p0x=2.5, p0y=3.5)
|
v2 = sfm_perspective_project_naive(vertices, fx=2.0, fy=2.0, p0x=2.5, p0y=3.5)
|
||||||
self.assertClose(v1, v2, atol=1e-6)
|
self.assertClose(v1, v2, atol=1e-6)
|
||||||
|
|
||||||
|
def test_perspective_type(self):
|
||||||
|
cam = PerspectiveCameras(focal_length=5.0, principal_point=((2.5, 2.5),))
|
||||||
|
self.assertTrue(cam.is_perspective())
|
||||||
|
self.assertEquals(cam.get_znear(), None)
|
||||||
|
@ -242,7 +242,10 @@ class TestRenderImplicit(TestCaseMixin, unittest.TestCase):
|
|||||||
rasterizer=MeshRasterizer(
|
rasterizer=MeshRasterizer(
|
||||||
cameras=cameras_randomized,
|
cameras=cameras_randomized,
|
||||||
raster_settings=RasterizationSettings(
|
raster_settings=RasterizationSettings(
|
||||||
image_size=image_size, blur_radius=1e-3, faces_per_pixel=10
|
image_size=image_size,
|
||||||
|
blur_radius=1e-3,
|
||||||
|
faces_per_pixel=10,
|
||||||
|
perspective_correct=False,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
shader=SoftPhongShader(
|
shader=SoftPhongShader(
|
||||||
|
@ -500,6 +500,7 @@ class TestRenderMeshes(TestCaseMixin, unittest.TestCase):
|
|||||||
blur_radius=np.log(1.0 / 1e-4 - 1.0) * blend_params.sigma,
|
blur_radius=np.log(1.0 / 1e-4 - 1.0) * blend_params.sigma,
|
||||||
faces_per_pixel=100,
|
faces_per_pixel=100,
|
||||||
clip_barycentric_coords=True,
|
clip_barycentric_coords=True,
|
||||||
|
perspective_correct=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Load reference image
|
# Load reference image
|
||||||
@ -844,7 +845,10 @@ class TestRenderMeshes(TestCaseMixin, unittest.TestCase):
|
|||||||
cameras = FoVPerspectiveCameras(device=device, R=R, T=T)
|
cameras = FoVPerspectiveCameras(device=device, R=R, T=T)
|
||||||
|
|
||||||
raster_settings = RasterizationSettings(
|
raster_settings = RasterizationSettings(
|
||||||
image_size=512, blur_radius=0.0, faces_per_pixel=1
|
image_size=512,
|
||||||
|
blur_radius=0.0,
|
||||||
|
faces_per_pixel=1,
|
||||||
|
perspective_correct=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
lights = PointLights(
|
lights = PointLights(
|
||||||
@ -919,7 +923,10 @@ class TestRenderMeshes(TestCaseMixin, unittest.TestCase):
|
|||||||
R, T = look_at_view_transform(2.7, 0.0, 0.0)
|
R, T = look_at_view_transform(2.7, 0.0, 0.0)
|
||||||
cameras = FoVPerspectiveCameras(device=device, R=R, T=T)
|
cameras = FoVPerspectiveCameras(device=device, R=R, T=T)
|
||||||
raster_settings = RasterizationSettings(
|
raster_settings = RasterizationSettings(
|
||||||
image_size=512, blur_radius=0.0, faces_per_pixel=1
|
image_size=512,
|
||||||
|
blur_radius=0.0,
|
||||||
|
faces_per_pixel=1,
|
||||||
|
perspective_correct=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Init shader settings
|
# Init shader settings
|
||||||
|
Loading…
x
Reference in New Issue
Block a user