Implement a perspective projection that maps 3D world points to 2D image coordinates using a camera's intrinsic matrix. This process is crucial in computer vision for understanding how 3D scenes are projected onto 2D images.
The intrinsic matrix, denoted as K, encapsulates the camera's internal parameters, including focal lengths (fx, fy) in pixels and the principal point (cx, cy), which represents the optical center of the camera. The intrinsic matrix K is given by
K=fx000fy0cxcy1
To project a 3D point (X, Y, Z) to a 2D image point, the following steps are involved:
Perform perspective division by dividing the X and Y coordinates by Z.
Apply the intrinsic matrixK to the normalized coordinates.
The projection equation can be represented as p=K⋅[X/Z,Y/Z,1]T.
K=fx000fy0cxcy1
This technique is widely used in 3D reconstruction and image processing applications.
Inputs:points_3d holds two camera-frame points, (0,0,10) and (5,5,10), both at depth Z=10. K has focal lengths fx=fy=500 pixels and principal point (cx,cy)=(320,240), the pixel where the optical axis hits the image.
Point 1: dividing by depth gives normalized coordinates (0/10,0/10)=(0,0). Multiplying K by (0,0,1)T leaves only the third column: u=500⋅0+320=320, v=500⋅0+240=240. A point on the optical axis always lands on the principal point.
Point 2:(5/10,5/10)=(0.5,0.5), so u=500⋅0.5+320=570 and v=500⋅0.5+240=490. The third component stays 1.
Output: one [u,v] pair per input point, rounded to 2 decimal places: [[320.0, 240.0], [570.0, 490.0]].
Notice that depth scales the offset: moving point 2 to Z=20 halves its shift from the centre, giving (445,365).
The task is to use the pinhole camera model with a known intrinsic matrixK to map 3D points (X,Y,Z) in camera coordinates to 2D pixel coordinates (u,v) on the image. Conceptually, this is just applying a 3×3 matrix and then doing a division by depth Z.
Below is the minimal theory and implementation strategy you need.
1. Background Knowledge (Key Concepts)
Pinhole camera model
A camera is modeled as a pinhole where 3D points project onto an image plane. In camera coordinates, a point (X,Y,Z) (with Z>0) projects to normalized image coordinates:
x=ZX,y=ZY
These are measured in units of focal length, not pixels.
Camera intrinsics K
The intrinsic matrix converts normalized camera coordinates (x,y,1) into pixel coordinates (u,v,1):
K=fx000fy0cxcy1
where:
fx,fy: focal lengths in pixels (may differ due to pixel aspect ratio),
cx,cy: principal point (optical center) in pixel coordinates.
Projection:
uv1=Kxy1=KX/ZY/Z1
Homogeneous coordinates
Often written as:
ph=KXYZ=u′v′w′
and then you get pixel coordinates by dividing:
u=w′u′,v=w′v′
For this simple case, w′=Z.
2. Algorithm / Approach
For each 3D point in camera coordinates:
Option A (explicit formula)
Use:
u=fxZX+cx,v=fyZY+cy
Option B (matrix form)
Form homogeneous 3D vector Pc=(X,Y,Z)T.
Compute ph=K\mathbf{P}c=(u′,v′,w′)T.
Get pixel coordinates: u=u′/w′, v=v′/w′.
In code, you typically use vectorized matrix multiplication (e.g., with NumPy) over all points.
3. Step-by-Step Strategy
Read inputs
Intrinsic parameters fx,fy,cx,cy.
A list/array of 3D points (Xi,Yi,Zi) in camera coordinates.
Build the intrinsic matrix
import numpy as np
K = np.array([
[fx, 0, cx],
[0, fy, cy],
[0, 0, 1]
], dtype=float)
Form homogeneous 3D points
If you have an array P of shape (N, 3) with rows [X, Y, Z], you can use it directly for matrix multiplication with K transposed:
# P shape: (N, 3)
P = points_3d # [[X1, Y1, Z1],..., [XN, YN, ZN]]
Apply projection
# p_h will be shape (N, 3), each row [u', v', w']
p_h = (K @ P.T).T