Pinhole Camera#
This module contains the functions and data structures needed to describe the projection of a 3D scene onto a 2D image plane.
In computer vision, we can map between the 3D world and a 2D image using projective geometry. The module implements the simplest camera model, the pinhole camera, which is the most basic model for general projective cameras from the finite cameras group.
The Pinhole Camera model is shown in the following figure:
Using this model, a scene view can be formed by projecting 3D points into the image plane using a perspective transformation.
or
- where:
\(M'\) is a 3D point in space with coordinates \([X,Y,Z]^T\) expressed in a Euclidean coordinate frame known as the world coordinate system.
\(m'\) is the projection of the 3D point \(M'\) onto the image plane with coordinates \([u,v]^T\) expressed in pixel units.
\(K\) is the camera calibration matrix, also referred to as the intrinsic matrix.
\(C\) is the principal point offset with coordinates \([u_0, v_0]^T\) at the origin of the image plane.
\(f_x, f_y\) are the focal lengths expressed in pixel units.
The camera rotation and translation are expressed in terms of a Euclidean coordinate frame known as the world coordinate system. These terms are usually expressed by the joint rotation-translation matrix \([R|t]\), also known as the extrinsic matrix. It describes the camera pose around a static scene and transforms the coordinates of a 3D point \((X,Y,Z)\) from the world coordinate system to the camera coordinate system.
The PinholeCamera expects the intrinsic matrices and the extrinsic matrices
to be of shape (B, 4, 4) such that each intrinsic matrix has the following format:
And each extrinsic matrix has the following format:
- class kornia.geometry.camera.pinhole.PinholeCamera(intrinsics, extrinsics, height, width)[source]#
Class that represents a Pinhole Camera model.
- Convention:
intrinsicsis the \((B, 4, 4)\) calibration matrix whose top-left \(3 \times 3\) block is[[fx, 0, cx], [0, fy, cy], [0, 0, 1]], andextrinsicsthe \((B, 4, 4)\) world-to-camera transform[R | t](OpenCV / COLMAP semantics):project()takes world points, computesK (R X + t)and returns pixels, whileunproject()takes pixels and a camera-frame depth and returns world points. The functional API takes a3x3Kand no extrinsics, so it works in the camera frame.pixel coordinates are
(u, v)= (column, row) with integer pixel centres: pixel(0, 0)is centred at(0, 0), ascreate_meshgrid()enumerates, so a centred image hascx = (W - 1) / 2,cy = (H - 1) / 2. COLMAP’s half-pixel convention reports the same principal point half a pixel larger.kornia.geometry.camera,kornia.geometry.depthandkornia.geometry.calibrationall use this convention; see Camera and world conventions across the ecosystem.depthis the camera-framez, except where anormalize/normalize_pointsflag reads it as the Euclidean ray length.the class owns copies of the tensors it is constructed from:
scale_()and thetx/ty/tzsetters update only the camera, andscale()andclone()return independent cameras.
Warning
scale()andscale_()rescale the principal point ascx' = s * cx(the half-pixel rule), which disagrees with the integer pixel centres above: #4263. With the \((B, N, 4, 4)\) storage the validator admits,project()raises on \((B, N, 3)\) points: #4266. Theintrinsicsform is not validated, butproject(),unproject(),intrinsics_inverse()andDepthWarperread only the top-left \(3 \times 3\) block, so a zero-paddedKbehaves like its homogeneous embedding.- Parameters:
intrinsics (
Tensor) – torch.Tensor with shape \((B, 4, 4)\) containing the full 4x4 camera calibration matrix. The shared shape validator also accepts \((B, N, 4, 4)\) forPinholeCamerasList, whileproject()requires the documented \((B, 4, 4)\) layout.extrinsics (
Tensor) – torch.Tensor with shape \((B, 4, 4)\) containing the full 4x4 rotation-translation matrix, checked by the same predicate.height (
Tensor) – torch.Tensor with shape \((B)\) containing the image height.width (
Tensor) – torch.Tensor with shape \((B)\) containing the image width.
Note
We assume that the class attributes are in batch form in order to take advantage of PyTorch parallelism to boost computing performance.
- property batch_size: int#
Return the batch size of the storage.
- Returns:
scalar with the batch size.
- property camera_matrix: Tensor#
Return the 3x3 camera matrix containing the intrinsics.
- Returns:
torch.Tensor of shape \((B, 3, 3)\).
- clone()[source]#
Return a deep copy of the current object instance.
See the Convention block on
PinholeCamera.- Return type:
- property cx: Tensor#
Return the x-coordinate of the principal point.
- Returns:
torch.Tensor of shape \((B)\).
- property cy: Tensor#
Return the y-coordinate of the principal point.
- Returns:
torch.Tensor of shape \((B)\).
- device()[source]#
Return the device for camera buffers.
- Return type:
- Returns:
Union[str, torch.device, None] type
- property extrinsics: Tensor#
The full 4x4 extrinsics matrix.
- Returns:
torch.Tensor of shape \((B, 4, 4)\).
- classmethod from_parameters(fx, fy, cx, cy, height, width, tx, ty, tz, batch_size, device, dtype)[source]#
Construct a batched pinhole camera from scalar parameter tensors.
See the Convention block on
PinholeCamera.This helper allocates batched \(4 \times 4\) intrinsic and extrinsic matrices, fills focal lengths/principal point/translation, and wraps them into a
PinholeCamerainstance.- Convention:
every parameter, including
heightandwidth, is broadcast overbatch_size.heightandwidthare stored as floating-point tensors of the requesteddtype, so the camera it builds can be scaled in place.
- Parameters:
fx (
Tensor) – Horizontal focal length per batch element.fy (
Tensor) – Vertical focal length per batch element.cx (
Tensor) – Principal point x-coordinate per batch element.cy (
Tensor) – Principal point y-coordinate per batch element.height (
int) – Image height in pixels.width (
int) – Image width in pixels.tx (
Tensor) – Camera translation along x per batch element.ty (
Tensor) – Camera translation along y per batch element.tz (
Tensor) – Camera translation along z per batch element.batch_size (
int) – Number of cameras in the batch.device (
Union[str,device,None]) – Target device for the created tensors.dtype (
dtype) – Target floating-point dtype for the created tensors.
- Return type:
- Returns:
Batched
PinholeCameraconfigured from the provided intrinsic and translation parameters.
- property fx: Tensor#
Return the focal length in the x-direction.
- Returns:
torch.Tensor of shape \((B)\).
- property fy: Tensor#
Return the focal length in the y-direction.
- Returns:
torch.Tensor of shape \((B)\).
- property intrinsics: Tensor#
The full 4x4 intrinsics matrix.
- Returns:
torch.Tensor of shape \((B, 4, 4)\).
- intrinsics_inverse()[source]#
Return the homogeneous 4x4 embedding of the inverse camera matrix.
Only the top-left 3x3 block of
intrinsicsis inverted. The remaining entries are ignored, so zero-padded intrinsics are supported. The result has a zero last row and column except for the homogeneous component at[..., 3, 3], which is one. See the Convention block onPinholeCamera.- Return type:
- Returns:
torch.Tensor of shape \((B, 4, 4)\).
- project(point_3d)[source]#
Project a 3d point in world coordinates onto the 2d camera plane.
See the Convention block on
PinholeCamera.- Convention:
point_3dmust be at least rank 2. An unbatched \((3,)\) point raisesValueError. An empty point set returns an empty result.a point whose camera-frame
zis 0 does not raise:Kis applied first and the perspective divide is then skipped, so the result is the undividedK (R X + t).
Warning
This
z = 0answer differs fromproject_points(), which appliesKafter the skipped divide: #4267.- Parameters:
point_3d (
Tensor) – torch.Tensor containing the 3d points to be projected to the camera plane. The shape of the torch.Tensor can be \((*, 3)\) with at least two dimensions.- Return type:
- Returns:
torch.Tensor of (u, v) cam coordinates with shape \((*, 2)\).
Example
>>> _ = torch.manual_seed(0) >>> X = torch.rand(1, 3) >>> K = torch.eye(4)[None] >>> E = torch.eye(4)[None] >>> h = torch.ones(1) >>> w = torch.ones(1) >>> pinhole = kornia.geometry.camera.PinholeCamera(K, E, h, w) >>> pinhole.project(X) tensor([[5.6088, 8.6827]])
- property rotation_matrix: Tensor#
Return the 3x3 rotation matrix from the extrinsics.
- Returns:
torch.Tensor of shape \((B, 3, 3)\).
- property rt_matrix: Tensor#
Return the 3x4 rotation-translation matrix.
- Returns:
torch.Tensor of shape \((B, 3, 4)\).
- scale(scale_factor)[source]#
Scale the pinhole model.
- Convention:
returns a new camera whose focal lengths, principal point and image size are multiplied by
scale_factor:fx' = s * fxandcx' = s * cx.height/widthtake the promoted dtype ofscale_factor * height.
Warning
The
cx' = s * cxrule disagrees with kornia’s integer pixel centres: #4263.- Parameters:
scale_factor (
Tensor) – a torch.Tensor with the scale factor. It has to be broadcastable with class members. The expected shape is \((B)\) or \((1)\).- Return type:
- Returns:
the camera model with scaled parameters.
- scale_(scale_factor)[source]#
Scale the pinhole model in-place.
- Convention:
applies the rescaling of
scale()in place and returnsself; the tensors passed to the constructor are not modified.
- property translation_vector: Tensor#
Return the translation vector from the extrinsics.
- Returns:
torch.Tensor of shape \((B, 3, 1)\).
- property tx: Tensor#
Return the x-coordinate of the translation vector.
- Returns:
torch.Tensor of shape \((B)\).
- property ty: Tensor#
Return the y-coordinate of the translation vector.
- Returns:
torch.Tensor of shape \((B)\).
- property tz: Tensor#
Returns the z-coordinate of the translation vector.
- Returns:
torch.Tensor of shape \((B)\).
- unproject(point_2d, depth)[source]#
Unproject a 2d point in 3d.
Transform coordinates in the pixel frame to the world frame.
See the Convention block on
PinholeCamera.- Parameters:
point_2d (
Tensor) – torch.Tensor containing the 2d to be projected to world coordinates. The shape of the torch.Tensor can be \((*, 2)\) with at least two dimensions.depth (
Tensor) – torch.Tensor containing the depth value of each 2d points. The torch.Tensor shape must be equal to point2d \((*, 1)\).
- Return type:
- Returns:
torch.Tensor of (x, y, z) world coordinates with shape \((*, 3)\).
Example
>>> _ = torch.manual_seed(0) >>> x = torch.rand(1, 2) >>> depth = torch.ones(1, 1) >>> K = torch.eye(4)[None] >>> E = torch.eye(4)[None] >>> h = torch.ones(1) >>> w = torch.ones(1) >>> pinhole = kornia.geometry.camera.PinholeCamera(K, E, h, w) >>> pinhole.unproject(x, depth) tensor([[0.4963, 0.7682, 1.0000]])
- kornia.geometry.camera.pinhole.cam2pixel(cam_coords_src, dst_proj_src, eps=1e-12)[source]#
Transform coordinates in the camera frame to the pixel frame.
See the Convention block on
PinholeCamera.- Convention:
dst_proj_srcis a \((B, 4, 4)\) projection matrix (thePinholeCameralayout, not a3x3K), and the result is(u, v)pixel coordinates in the destination frame.
Warning
The perspective division is
x / (z + eps)rather than a guarded divide, soz = 0givesx / eps, huge for a nonzerox(infwhereepsunderflows), andepsbiases every small depth: #4267.- Parameters:
cam_coords_src (
Tensor) – (x, y, z) coordinates defined in the first camera coordinates system. Shape must be BxHxWx3.dst_proj_src (
Tensor) – the projection matrix between the reference and the non reference camera frame. Shape must be Bx4x4.eps (
float, optional) – small value to avoid division by zero error. Default:1e-12
- Return type:
- Returns:
torch.Tensor of shape BxHxWx2 with (u, v) pixel coordinates.
- kornia.geometry.camera.pinhole.pixel2cam(depth, intrinsics_inv, pixel_coords)[source]#
Transform coordinates in the pixel frame to the camera frame.
See the Convention block on
PinholeCamera.- Convention:
intrinsics_invis a \((B, 4, 4)\) inverse calibration matrix (thePinholeCameralayout, not a3x3K), anddepthis the camera-framezat each pixel of the(u, v, 1)grid.a
depththat is notBx1xHxW, anintrinsics_invthat is not \((B, 4, 4)\) or apixel_coordsthat is notBxHxWx3raisesValueError; thatpixel_coordsmatches theHandWofdepthis not checked.
- Parameters:
- Return type:
- Returns:
torch.Tensor of shape BxHxWx3 with (x, y, z) cam coordinates.