Project 3D Point to Pixel
Project a 3D point in camera coordinates to 2D pixel coordinates.
The projection of a 3D point to 2D uses the pinhole camera model:
βuv1βββΌKβXYZββ
The "~" means equality up to scale. To get actual pixel coordinates:
-
Multiply: βxβ²yβ²zβ²ββ=Kβ βXYZββ
-
Normalize by Z: u=xβ²/zβ²,v=yβ²/zβ²
This implements perspective projection where distant objects appear smaller.
Example:
project_point([[1000,0,320],[0,1000,240],[0,0,1]], [0.1, 0.1, 1])
[420.0, 340.0]
Projecting point (0.1, 0.1, 1) through camera:
- Multiply K Γ point: x' = 1000Γ0.1 + 0Γ0.1 + 320Γ1 = 100 + 320 = 420 y' = 0Γ0.1 + 1000Γ0.1 + 240Γ1 = 100 + 240 = 340 z' = 0Γ0.1 + 0Γ0.1 + 1Γ1 = 1
- Normalize: u = 420/1 = 420, v = 340/1 = 340 Result: pixel (420, 340)
Constraints:
- K: 3x3 intrinsic matrix
- point_3d: [X, Y, Z] point in camera coordinates (Z > 0)
- Return [u, v] pixel coordinates rounded to 4 decimal places
More from CV: Structure from Motion and SLAM
To project a 3D point in camera coordinates to a 2D pixel, you apply a linear transform with the intrinsic matrix K and then normalize by the third coordinate to get (u,v).
1. Background Knowledge
In the pinhole camera model, a point in 3D camera coordinates (X,Y,Z) is mapped to the image plane by drawing a ray from the camera center through the point; where that ray intersects the image plane is the projection. Algebraically, this is modeled by a homogeneous linear transform followed by a division (perspective projection).
The intrinsic camera matrix K encodes the cameraβs internal parameters:
- focal lengths in pixels (fxβ,fyβ)
- principal point (cxβ,cyβ)
- optional skew (often 0)
A typical form is:
K=βfxβ00βsfyβ0βcxβcyβ1ββMultiplying K by the 3D point (X,Y,Z) in camera coordinates gives a point in homogeneous image coordinates, which you convert to pixel coordinates by dividing by its third component.
2. Algorithm / Approach
General pattern to project a 3D point in camera coordinates to pixels:
- Represent the 3D point as a homogeneous 3-vector (X,Y,Z).
- Multiply by the camera intrinsic matrix K to get (xβ²,yβ²,zβ²).
- Convert from homogeneous to Euclidean image coordinates:
- u=xβ²/zβ²
- v=yβ²/zβ²
- Return (u,v) as the pixel coordinates.
This is just a matrix multiply + perspective divide.
3. Step-by-Step Strategy
Assume inputs:
- Intrinsic matrix K (3Γ3)
- 3D point in camera frame (X,Y,Z)
Steps:
- Matrix multiplication
import numpy as np
K =... # 3x3 intrinsic matrix
X_cam = np.array([X, Y, Z]) # shape (3,)
x_prime = K @ X_cam # shape (3,)
# x_prime = [x', y', z']
- Perspective division
x_p, y_p, z_p = x_prime
u = x_p / z_p
v = y_p / z_p
- Output
- Return u, v as the pixel coordinates.
- Optionally cast to int if you need discrete pixel indices (after any rounding).
Mathematically, you are implementing:
βxβ²yβ²zβ²ββ=KβXYZββ,u=zβ²xβ²β,v=zβ²yβ²β.4. Common Pitfalls
- Forgetting the division by zβ²: Just doing K @ X_cam gives homogeneous coordinates, not final pixel coordinates.
- Using world coordinates instead of camera coordinates: This step assumes the point is already in the camera frame. If given world coordinates, you must first apply extrinsics [Rβ£t].
- Z β€ 0:
- If Zβ€0 (or zβ²β€0), the point is behind the camera or on the camera center; projection is invalid.
- Integer rounding too early:
- Do all math in floating point and only convert to int when you need to index into an image.
- Row vs column convention:
- Make sure your matrix multiplication is consistent (e.g., using column vectors and K@X as in the math).
5. Time & Space Complexity
For a single point:
- Time complexity:
- Matrixβvector multiply: constant work (3Γ3 with 3Γ1) β O(1).
- Divisions and assignments: O(1).
- Space complexity:
- A few 3D vectors and scalars β O(1) extra space.
For N points, if you vectorize:
- Time: O(N) (each point gets one 3Γ3 multiply + divide).
- Space: O(N) to store all projected pixels.