Projective Geometry for Computer Vision
Projective geometry is the rulebook for what stays true when 3D becomes 2D: straight lines stay straight, but parallels can meet. The meeting point is the vanishing point, and it encodes direction.
Why Does This Exist?
Photos break Euclidean habits: railway rails meet, hallway corners stop looking square, and equal-spaced windows shrink unevenly. Before estimating anything from images you need to know which properties survive projection and which die. Projective geometry is that contract. It needs homogeneous coordinates as its language: directions become points at infinity, and projection becomes matrix algebra.
Think of It Like This
Railway tracks from a level crossing
Stand on a crossing and look down the line: the rails visibly meet at the horizon. Walk a mile toward that meeting spot and the rails beside you are still parallel steel, a fixed gauge apart. The meeting point was never a place; it is the direction you looked, drawn on the sky.
That is a vanishing point. Every set of parallel world lines gets exactly one, fixed by its direction and the camera, never by how far the lines run. The analogy stops at distance: the horizon looks reachable, but no vanishing point corresponds to any finite 3D location.
How It Actually Works
A world direction (a unit -vector, the heading of a family of parallel lines) images to the vanishing point , written in homogeneous pixels and divided through as usual. Here rotates the direction into the camera frame and applies the intrinsics; translation plays no role because directions ignore position. The vanishing line of a plane (its horizon) is the image of all its directions at once.
What survives projection: straight lines stay straight, and the cross-ratio of four collinear points is preserved. What dies: parallelism, angles, and length ratios. So a rectangle may image as any quadrilateral, but its edges stay lines, which is why plane rectification is possible at all.
Worked numbers
Take with and , the identity, and rails running along (forward and right in equal parts):
Both rails converge on pixel , off the right edge of a -wide image, which is normal: vanishing points routinely fall outside the frame. A second family along would meet at instead, showing that the point encodes direction, one direction per point.
Code
def vanishing_point(fx: float, cx: float, cy: float, dx: float, dz: float) -> tuple[float, float]: return (fx * dx / dz + cx, cy) # K times R times d, with R as identity
print(vanishing_point(800.0, 320.0, 240.0, 1.0, 1.0)) # -> (1120.0, 240.0)Watch Out For
Measuring angles in the raw photo
Perspective does not preserve angles, so a wall corner that is square in the world can read degrees in pixels. Estimating wall orientation or object pose from unrectified angles bakes that skew into the answer. Rectify the plane with a homography first, then measure in the flattened view where angles are honest again.
Reading depth out of a vanishing point
A vanishing point fixes a direction and nothing else. Two identical rails at different distances share it exactly, so it cannot tell near from far; that is the same scale ambiguity structure from motion fights. Take direction from the vanishing point, then get distance from a second cue such as stereo or a known size.
The Quick Version
- Vanishing points image world directions: , with no translation involved.
- Straight lines survive projection; parallelism, angles, and ratios do not.
- One direction gives one vanishing point, even shared by lines at any distance.
- Vanishing points often fall outside the image frame, which is fine.
- Rectify a plane before measuring angles or lengths on it.
- Direction from a vanishing point never implies distance.