Camera Extrinsics: Position and Rotation
Extrinsics say where the camera stands and where it looks: a rotation plus a translation that move world points into the camera's own coordinate frame. Move the camera and only these numbers change.
Why Does This Exist?
Intrinsics never change when the camera moves, so they cannot say where anything is. A robot driving through a room sees the same chair at different pixels every second, and the only thing changing is the camera's own position and heading. Extrinsics carry exactly that: the pose that converts fixed world coordinates into the camera's current point of view.
The internal half of the pipeline is intrinsic parameters; the page that measures both halves is camera calibration and parameters. This page covers the pose half: what and mean, how to apply them, and the two sign errors everyone makes once.
Think of It Like This
A tourist with a paper map
You hold a city map with north pointing up. A landmark is marked two blocks east, one block north: those are world coordinates. To walk there you translate the mark into body coordinates: turn to face east, then it is two blocks ahead and one block left. Your heading is the rotation, your street corner is the translation.
The analogy stops at the eyes: the tourist still needs vision to see anything, which is the intrinsics half. Pose only answers "relative to me," never "on my sensor."
How It Actually Works
A world point becomes a camera-frame point through . Here is a rotation matrix (orthonormal rows and columns, determinant , so no mirroring or scaling) and is a -vector. Together they carry degrees of freedom: for orientation, for position. Apply first, then add .
Worked numbers
Yaw the camera degrees about the vertical axis with no translation, so and . Take :
The point swings sideways in and while its depth stays put, as it must for a pure rotation. Projection would then divide by that unchanged .
Code
import math
def to_camera(xw: float, yw: float, yaw_deg: float) -> tuple[float, float]: a = math.radians(yaw_deg) # rotation about the vertical axis return (round(math.cos(a) * xw - math.sin(a) * yw, 2), round(math.sin(a) * xw + math.cos(a) * yw, 2))
print(to_camera(1.0, 0.0, 30.0)) # -> (0.87, 0.5)Watch Out For
Mixing up active and passive rotations
here is passive: it rewrites fixed points into a turned frame. Its transpose is the active twin that turns points inside a fixed frame. Grab the wrong one and the whole scene rotates backwards on screen, which reads as a tracking failure rather than a one-character bug. Remember the direction this page's equation moves: world points go into the camera frame.
Plotting t as the camera position
is not where the camera stands. It is where the world origin lands as seen by the camera. The camera center in world coordinates is . Plotting raw values as a trajectory mirrors and shifts the true path, and the error grows with distance from the origin. Convert with the formula before drawing any path, the way visual SLAM systems must before closing loops.
The Quick Version
- Extrinsics are a rotation plus a translation , six degrees of freedom total.
- They map world points into the camera frame: .
- must stay orthonormal with determinant , or mirrors and scales creep in.
- The camera center in world coordinates is , not .
- Moving the camera changes only the extrinsics; the intrinsics stay fixed.