gradslam.geometry

gradslam.geometry.projutils

homogenize_points(pts: torch.Tensor)[source]

Convert a set of points to homogeneous coordinates.

Parameters

pts (torch.Tensor) – Tensor containing points to be homogenized.

Returns

Homogeneous coordinates of pts.

Return type

torch.Tensor

Shape:
  • pts: \((N, *, K)\) where \(N\) indicates the number of points in a cloud if the shape is \((N, K)\) and indicates batchsize if the number of dimensions is greater than 2. Also, \(*\) means any number of additional dimensions, and K is the dimensionality of each point.

  • Output: \((N, *, K + 1)\) where all but the last dimension are the same shape as pts.

Examples:

>>> pts = torch.rand(10, 3)
>>> pts_homo = homogenize_points(pts)
>>> pts_homo.shape
torch.Size([10, 4])
unhomogenize_points(pts: torch.Tensor, eps: float = 1e-06)torch.Tensor[source]

Convert a set of points from homogeneous coordinates to Euclidean coordinates. This is usually done by taking each point \((X, Y, Z, W)\) and dividing it by the last coordinate \((w)\).

Parameters

pts (torch.Tensor) – Tensor containing points to be unhomogenized.

Returns

‘Unhomogenized’ points

Return type

torch.Tensor

Shape:
  • pts: \((N, *, K)\) where \(N\) indicates the number of points in a cloud if the shape is \((N, K)\) and indicates batchsize if the number of dimensions is greater than 2. Also, \(*\) means any number of additional dimensions, and K is the dimensionality of each point.

  • output: \((N, *, K-1)\) where all but the last dimension are the same shape as pts.

Examples:

>>> pts = torch.rand(10, 3)
>>> pts_unhomo = unhomogenize_points(pts)
>>> pts_unhomo.shape
torch.Size([10, 2])
project_points(cam_coords: torch.Tensor, proj_mat: torch.Tensor, eps: Optional[float] = 1e-06)torch.Tensor[source]

Projects points from the camera coordinate frame to the image (pixel) frame.

Parameters
  • cam_coords (torch.Tensor) – pixel coordinates (defined in the frame of the first camera).

  • proj_mat (torch.Tensor) – projection matrix between the reference and the non-reference camera frame.

Returns

Image (pixel) coordinates corresponding to the input 3D points.

Return type

torch.Tensor

Shapes:
  • cam_coords: \((N, *, 3)\) or \((*, 4)\) where \(*\) indicates an arbitrary number of dimensions. Here \(N\) indicates the number of points in a cloud if the shape is \((N, 3)\) and indicates batchsize if the number of dimensions is greater than 2.

  • proj_mat: \((*, 4, 4)\) where \(*\) indicates an arbitrary number of dimensions. dimension contains a \((4, 4)\) camera projection matrix.

  • Output: \((N, *, 2)\), where \(*\) indicates the same dimensions as in cam_coords. Here \(N\) indicates the number of points in a cloud if the shape is \((N, 3)\) and indicates batchsize if the number of dimensions is greater than 2.

Examples:

>>> # Case 1: Input cam_coords are homogeneous, no batchsize dimension.
>>> cam_coords = torch.rand(10, 4)
>>> proj_mat = torch.rand(4, 4)
>>> pixel_coords = project_points(cam_coords, proj_mat)
>>> pixel_coords.shape
torch.Size([10, 2])
>>> # Case 2: Input cam_coords are homogeneous and batched. Broadcast proj_mat across batch.
>>> cam_coords = torch.rand(2, 10, 4)
>>> proj_mat = torch.rand(4, 4)
>>> pixel_coords = project_points(cam_coords, proj_mat)
>>> pixel_coords.shape
torch.Size([2, 10, 2])
>>> # Case 3: Input cam_coords are homogeneous and batched. A different proj_mat applied to each element.
>>> cam_coords = torch.rand(2, 10, 4)
>>> proj_mat = torch.rand(2, 4, 4)
>>> pixel_coords = project_points(cam_coords, proj_mat)
>>> pixel_coords.shape
torch.Size([2, 10, 2])
>>> # Case 4: Similar to case 1, but cam_coords are unhomogeneous.
>>> cam_coords = torch.rand(10, 3)
>>> proj_mat = torch.rand(4, 4)
>>> pixel_coords = project_points(cam_coords, proj_mat)
>>> pixel_coords.shape
torch.Size([10, 2])
>>> # Case 5: Similar to case 2, but cam_coords are unhomogeneous.
>>> cam_coords = torch.rand(2, 10, 3)
>>> proj_mat = torch.rand(4, 4)
>>> pixel_coords = project_points(cam_coords, proj_mat)
>>> pixel_coords.shape
torch.Size([2, 10, 2])
>>> # Case 6: Similar to case 3, but cam_coords are unhomogeneous.
>>> cam_coords = torch.rand(2, 10, 3)
>>> proj_mat = torch.rand(2, 4, 4)
>>> pixel_coords = project_points(cam_coords, proj_mat)
>>> pixel_coords.shape
torch.Size([2, 10, 2])
unproject_points(pixel_coords: torch.Tensor, intrinsics_inv: torch.Tensor, depths: torch.Tensor)torch.Tensor[source]

Unprojects points from the image (pixel) frame to the camera coordinate frame.

Parameters
  • pixel_coords (torch.Tensor) – pixel coordinates.

  • intrinsics_inv (torch.Tensor) – inverse of the camera intrinsics matrix.

  • depths (torch.Tensor) – per-pixel depth estimates.

Returns

camera coordinates

Return type

torch.Tensor

Shapes:
  • pixel_coords: \((N, *, 2)\) or \((*, 3)\), where * indicates an arbitrary number of dimensions. Here \(N\) indicates the number of points in a cloud if the shape is \((N, 3)\) and indicates batchsize if the number of dimensions is greater than 2.

  • intrinsics_inv: \((*, 3, 3)\), where * indicates an arbitrary number of dimensions.

  • depths: \((N, *)\) where * indicates the same number of dimensions as in pixel_coords. Here \(N\) indicates the number of points in a cloud if the shape is \((N, 3)\) and indicates batchsize if the number of dimensions is greater than 2.

  • output: \((N, *, 3)\) where * indicates the same number of dimensions as in pixel_coords. Here \(N\) indicates the number of points in a cloud if the shape is \((N, 3)\) and indicates batchsize if the number of dimensions is greater than 2.

Examples:

>>> # Case 1: Input pixel_coords are homogeneous, no batchsize dimension.
>>> pixel_coords = torch.rand(10, 3)
>>> intrinsics_inv = torch.rand(3, 3)
>>> depths = torch.rand(10)
>>> cam_coords = unproject_points(pixel_coords, intrinsics_inv, depths)
>>> cam_coords.shape
torch.Size([10, 3])
>>> # Case 2: Input pixel_coords are homogeneous, with a batchsize dimension. But, intrinsics_inv is not.
>>> pixel_coords = torch.rand(2, 10, 3)
>>> intrinsics_inv = torch.rand(3, 3)
>>> depths = torch.rand(2, 10)
>>> cam_coords = unproject_points(pixel_coords, intrinsics_inv, depths)
>>> cam_coords.shape
torch.Size([2, 10, 3])
>>> # Case 3: Input pixel_coords are homogeneous, with a batchsize dimension. intrinsics_inv is batched.
>>> pixel_coords = torch.rand(2, 10, 3)
>>> intrinsics_inv = torch.rand(2, 3, 3)
>>> depths = torch.rand(2, 10)
>>> cam_coords = unproject_points(pixel_coords, intrinsics_inv, depths)
>>> cam_coords.shape
torch.Size([2, 10, 3])
>>> # Case 4: Similar to case 1, but input pixel_coords are unhomogeneous.
>>> pixel_coords = torch.rand(10, 2)
>>> intrinsics_inv = torch.rand(3, 3)
>>> depths = torch.rand(10)
>>> cam_coords = unproject_points(pixel_coords, intrinsics_inv, depths)
>>> cam_coords.shape
torch.Size([10, 3])
>>> # Case 5: Similar to case 2, but input pixel_coords are unhomogeneous.
>>> pixel_coords = torch.rand(2, 10, 2)
>>> intrinsics_inv = torch.rand(3, 3)
>>> depths = torch.rand(2, 10)
>>> cam_coords = unproject_points(pixel_coords, intrinsics_inv, depths)
>>> cam_coords.shape
torch.Size([2, 10, 3])
>>> # Case 6: Similar to case 3, but input pixel_coords are unhomogeneous.
>>> pixel_coords = torch.rand(2, 10, 2)
>>> intrinsics_inv = torch.rand(2, 3, 3)
>>> depths = torch.rand(2, 10)
>>> cam_coords = unproject_points(pixel_coords, intrinsics_inv, depths)
>>> cam_coords.shape
torch.Size([2, 10, 3])
inverse_intrinsics(K: torch.Tensor, eps: float = 1e-06)torch.Tensor[source]

Efficient inversion of intrinsics matrix

Parameters
  • K (torch.Tensor) – Intrinsics matrix

  • eps (float) – Epsilon for numerical stability

Returns

Inverse of intrinsics matrices

Return type

torch.Tensor

Shape:
  • K: \((*, 4, 4)\) or \((*, 3, 3)\)

  • Kinv: Matches shape of K (\((*, 4, 4)\) or \((*, 3, 3)\))