v9.1.1
Menu

Triangulation of 3D Points

mediumPROBundle Adjustment for SfMSfMCV: Structure from Motion and SLAM

Implement a linear triangulation method to estimate 3D points from two camera views. This technique is crucial in Structure from Motion (SfM) and Bundle Adjustment for reconstructing 3D scenes from 2D images.

The goal is to find the 3D point XX that minimizes the reprojection error between the observed 2D points x1x_1 and x2x_2 in two camera views, given the camera matrices P1P_1 and P2P_2.

Here are the steps to follow:

  1. For each point pair, build a 4×44 \times 4 matrix AA from the camera matrices and the 2D points (below), where PkP^k is the kk-th row of PP.
  2. Apply Singular Value Decomposition (SVD) to AA to find the homogeneous point X~=(X,Y,Z,W)\tilde X = (X, Y, Z, W) with AX~≈0A\tilde X \approx 0.
  3. Dehomogenize: divide by WW to get (X/W, Y/W, Z/W)(X/W,\ Y/W,\ Z/W).
A=[u1P13−P11v1P13−P12u2P23−P21v2P23−P22]A = \begin{bmatrix} u_1 P_1^3 - P_1^1 \\ v_1 P_1^3 - P_1^2 \\ u_2 P_2^3 - P_2^1 \\ v_2 P_2^3 - P_2^2 \end{bmatrix}

Return the 3D points as a NumPy array of shape (N,3)(N, 3), one row per point pair.

This technique is widely used in computer vision applications, such as 3D reconstruction and Simultaneous Localization and Mapping (SLAM).

Example

Input
P1 = K @ [I | 0]  # First camera at origin
P2 = K @ [R | t]  # Second camera
pts1 = [[u1, v1], ...]
pts2 = [[u2, v2], ...]
Output
3D points [[X, Y, Z], ...]
Reasoning
  • Inputs: P1,P2P_1, P_2 are 3×43 \times 4 projection matrices; pts1 and pts2 hold NN matching image points (u,v)(u, v), one per row. Take P1=[I∣0]P_1 = [I \mid 0], P2=[I∣(−1,0,0)T]P_2 = [I \mid (-1, 0, 0)^T], with x1=(0.2,0.4)x_1 = (0.2, 0.4) and x2=(0,0.4)x_2 = (0, 0.4).
  • Rows of AA: 0.2 P13−P11=(−1,0,0.2,0)0.2\,P_1^3 - P_1^1 = (-1, 0, 0.2, 0), 0.4 P13−P12=(0,−1,0.4,0)0.4\,P_1^3 - P_1^2 = (0, -1, 0.4, 0), 0⋅P23−P21=(−1,0,0,1)0 \cdot P_2^3 - P_2^1 = (-1, 0, 0, 1), 0.4 P23−P22=(0,−1,0.4,0)0.4\,P_2^3 - P_2^2 = (0, -1, 0.4, 0).
  • Null space: a homogeneous point X~=(X,Y,Z,W)\tilde X = (X, Y, Z, W) projecting onto both pixels satisfies AX~=0A\tilde X = 0; here that unit vector is (0.1796,0.3592,0.8980,0.1796)(0.1796, 0.3592, 0.8980, 0.1796). With noisy pixels, take the unit X~\tilde X minimising ∥AX~∥\lVert A\tilde X \rVert.
  • Dehomogenise: dividing by W=0.1796W = 0.1796 gives (1,2,5)(1, 2, 5). Check: it reprojects to (0.2,0.4)(0.2, 0.4) and (0,0.4)(0, 0.4).
  • Output: an N×3N \times 3 array, here one row (1,2,5)(1, 2, 5). Notice depth comes from disparity: a shift of 0.20.2 over a baseline of 11 gives Z=1/0.2=5Z = 1/0.2 = 5. Identical pixels in both views mean parallel rays and W→0W \to 0: a point at infinity.

Constraints

  • P1, P2: Camera projection matrices (3, 4)
  • pts1, pts2: Corresponding 2D points (N, 2)
  • Return: 3D points (N, 3)

Learn this in

More from CV: Structure from Motion and SLAM

PRO

Editor locked

The code editor is locked for Pro problems. It is only available for free problems. Please upgrade to gain access to the code editor for all problems.

solution.py

Test results

Sign in to run your code against the test cases.