BookNotesSlidesP-sets Syllabusdraft · v0.2.49.1
◀▲⌂▶
💬Comments welcome. To leave a note, select any text and click the note / highlight button that pops up — or open the panel with the tab at the top-right (‹). Notes are visible only inside our private review group.

20.1 Manual panorama stitching from multiple views⧉

📎 Problem set

PS6 solves a homography from four point pairs and stitches a planar mosaic. → Chapter 1.5, Problem sets (appendix).

Overlapping photographs can cover a scene wider than one frame. Stitching requires a map between their common content. For an ideal pinhole camera rotating about a fixed projection center, or for points on one plane, that map is a homography. Start by clicking correspondences; Chapter 20.2, Automatic panorama stitching from multiple views and feature matching replaces those clicks with feature matches.

20.1.1 The scenario, and the one rule: rotate, don't translate⧉

Here is the setup. You stand in one place and pan the camera across a scene, taking overlapping frames. Choose one frame as the reference; reproject, or warp, the others into its coordinate system; blend the overlaps. The output is a virtual wide-angle view assembled from shots no single exposure could have captured (Figure 20.1.1).

For a general scene, keep the camera's effective projection center approximately fixed as it turns. The ideal rotation model then relates visible scene points independently of depth. In practice, lens distortion, rolling shutter and viewpoint shifts can violate it. A panorama head adjusted around the no-parallax position reduces viewpoint shifts.

Translation creates depth-dependent parallax: a nearby railing shifts relative to a distant building. One homography generally cannot align both. Local warps or depth-aware reconstruction can address some of the discrepancy; translation does not make every possible two-dimensional correspondence map impossible. A planar scene remains an important homography case.

One pointer, in keeping with our standing division of labor. The warping itself (forward vs. inverse warp, resampling, antialiasing) and the closely related perspective-distortion correction are developed in Matching pixels across space and time. Here we need only the geometry (which $H$ relates the views) and how to solve for it.

fig-pano-4clicks
Figure 20.1.1. The manual stitching pipeline end to end, on two real overlapping frames of MIT's Stata Center (Frank Gehry). Top: the user clicks four pairs of corresponding points across the overlap (the colored lines link matching landmarks on the building). From those four correspondences, solve for the homography $H$ ($3\times3$, 8 DOF); bottom: warp the second frame into the first's coordinate frame and feather-blend the overlap into a single wide image (the dashed box marks frame 1's footprint). The four clicks are the only manual step: everything downstream is mechanical.
fig-pano-rotate-vs-translate
Figure 20.1.2. Rotate, don't walk. Top: one fixed optical center, the camera fanning across the scene, so the views overlap and are related everywhere by a single homography, whatever the depths. Bottom: a camera that translates between shots, so near and far objects shift by different amounts (parallax) and no single 2D map aligns the views; the foreground slides relative to the background. Panorama stitching requires the top case.

20.1.2 Refresher: pinhole projection is "divide by depth"⧉

Everything below is a consequence of one fact about the pinhole camera, so let us refresh it. A 3D point $(x,y,z)$ in the camera's frame images to the point $(x/z,\,y/z)$ on the plane $z=1$. Projection is division by depth. This is why far things look small: a larger $z$ shrinks $(x/z,y/z)$ toward the center. The whole nonlinearity of perspective lives in that single divide.

Define $R$ to transform a ray expressed in camera 1 coordinates into camera 2 coordinates. If the camera-to-world orientations are $Q_1,Q_2$, then $R=Q_2^{\mathsf T}Q_1$. This convention avoids confusing a physical camera rotation with the inverse coordinate transform.

We know the ray from each source pixel, but not the depth of the scene point along it. Under pure rotation, all positive depths along that ray share the same destination direction.

20.1.3 Why you don't need 3D: depth cancels for a pure rotation⧉

The idea is best stated as an observation about a single viewing ray: all points along one viewing ray reproject to the same place. A pixel $(x,y)$ in image 1 is the image of an entire ray of 3D points $(tx,\,ty,\,t)$, one for every depth $t$, all sharing the same direction. Rotate that whole ray by $R$ and re-project. The rotation scales linearly, so the rotated ray is $R\,(tx,ty,t)^\top = t\,R\,(x,y,1)^\top$: the depth $t$ is a common factor of all three coordinates. But projection divides by the third coordinate, and dividing kills that common factor. Every point on the ray, at every depth, lands on the exact same pixel in the rotated view. The destination pixel does not depend on depth at all (Figure 20.1.3).

We may therefore represent the source ray at any convenient nonzero scale. Rotating it and dividing by its third coordinate gives the same destination pixel regardless of the chosen depth.

Chaining the three steps, un-project (apply $K^{-1}$ to go from pixels to rays), rotate (apply $R$), re-project (apply $K$ to go from rays back to pixels), gives the view-to-view map

$$ \mathbf{x}' \simeq H\,\mathbf{x}, \qquad H = K_2\,R\,K_1^{-1}, $$

Here $K_1,K_2$ are the two intrinsics matrices and $R$ follows the convention above. With equal intrinsics this becomes $KRK^{-1}$; with normalized image coordinates it becomes $R$. The relation holds for rays with a valid destination projection, not for all output locations regardless of visibility.

The pure-rotation model avoids estimating scene depth. Fitting and rendering it still require numerical care, and geometric error minimization is nonlinear even though an algebraic initialization can be obtained linearly.

fig-depth-cancels-ray
Figure 20.1.3. Depth cancels for a pure rotation. A single viewing ray through the optical center carries scene points at many depths $(tx,ty,t)$; pinhole projection maps each to $(x/z,y/z)$, project is division by depth. Rotating the ray by $R$ multiplies all three coordinates by the same $t$; re-projecting divides it back out, so every point on the ray, near or far, reprojects to the same pixel in the rotated view. The destination pixel depends on the ray's direction and on $R$, never on depth, which is why we may simply set $z=1$.

20.1.4 Homographies and homogeneous coordinates⧉

The map $\mathbf{x}'\simeq H\mathbf{x}$ deserves its own vocabulary, because the same object recurs throughout the rest of the part. We have been implicitly using homogeneous coordinates: represent a 2D point $(u,v)$ by three numbers $(x,y,w)$, with $u=x/w$ and $v=y/w$. To recover the ordinary Euclidean point you divide by the last coordinate. A point therefore has no unique triple: every scaling $(wx,wy,w)$ names the same point, so homogeneous coordinates are defined up to scale. Two payoffs justify the bookkeeping. First, they make perspective (that very divide) and translation expressible as a single matrix multiply. Second, they are literally "treat the image as a plane at $z=1$ in 3D," which is exactly the picture from the previous section.

A homography is represented by an invertible $3\times3$ matrix up to nonzero scale. It preserves straight lines, but can send points to infinity where the homogeneous denominator vanishes. Not every arbitrary corner arrangement gives a finite, nonsingular warp of the entire source rectangle.

How much freedom does $H$ have? It has nine entries, but it is defined up to scale, since $H$ and $kH$ produce the same map, because scaling all of $(w'x',\,w'y',\,w')$ by $k$ leaves the Euclidean point $(x',y')$ unchanged. So a homography has 8 degrees of freedom, not 9. It tells us exactly how much data we need: 4 point correspondences supply 8 numbers, just enough to pin $H$ down. (This is the same $s=4$ minimal sample random sample consensus (RANSAC) draws in the next chapter, Chapter 20.2, Automatic panorama stitching from multiple views and feature matching.)

Writing out $H=\left(\begin{smallmatrix}a&b&c\\ d&e&f\\ g&h&i\end{smallmatrix}\right)$, the per-point formula is

$$ x'=\frac{ax+by+c}{gx+hy+i}, \qquad y'=\frac{dx+ey+f}{gx+hy+i}. $$

The shared denominator $w'=gx+hy+i$ is the perspective divide; the entries $g$ and $h$ are what make parallel lines converge. Setting $g=h=0$ (and $i\neq0$) makes the denominator constant, which removes the perspective entirely and leaves a plain affine map. This standard projective-geometry material is laid out at length in Hartley and Zisserman and Szeliski.

fig-homography-quad
Figure 20.1.4. What a homography does to a plane. The input rectangle (left) maps to an arbitrary quadrilateral (right): parallel edges need not stay parallel; they may converge toward a vanishing point, but every straight line stays straight. This is the most general projective map of a plane, with 8 degrees of freedom; an affine map (no perspective) would keep the rectangle a parallelogram.
fig-pano-homography
Figure 11.1.4 (reproduced). Homography refresher (interactive). Get a feel for the $3\times3$ map before we solve for it: drag the four corners of a single image to reproject it and watch the matrix update, or edit the coefficients directly and watch the corners move. Zero the bottom-row perspective terms $g,h$ and the warp drops to affine, a parallelogram, no convergence; restore them for full projective freedom. The four draggable corners are the four correspondences that fix all eight degrees of freedom, exactly the four you will click to stitch in the next section. (The same sandbox introduces the homography in Chapter 11.1, Warping and resampling.)

20.1.5 Solving for $H$ from correspondences⧉

The goal is concrete: given $\geq 4$ matched point pairs $\mathbf{x}_i \leftrightarrow \mathbf{x}_i'$, find the homography $H$ that maps each $\mathbf{x}_i$ to $\mathbf{x}_i'$. In manual stitching the user supplies these pairs by clicking matching landmarks across the overlap; automatically they come from feature matching (next chapter).

At first glance $\mathbf{x}'\simeq H\mathbf{x}$ looks nonlinear, because of the divide. The trick is to clear the denominator by cross-multiplying. Take $x' = (ax+by+c)/(gx+hy+i)$, multiply both sides by the denominator, and you get $ax+by+c-x'(gx+hy+i)=0$, a single equation that is now linear in the unknown entries of $H$. Each correspondence yields two such equations (one from $x'$, one from $y'$). Stack them into

$$ A\,\mathbf{h} = \mathbf{0}, $$

where $\mathbf{h}$ is the 9-vector of $H$'s entries and $A$ has two rows per correspondence. Four pairs give 8 equations.

The all-zero vector trivially solves the homogeneous equations and cannot represent a homography. Direct linear transformation (DLT) instead minimizes $\lVert A\mathbf h\rVert^2$ subject to $\lVert\mathbf h\rVert=1$, using a right singular vector. Before fitting, normalize coordinates in each image to zero centroid and mean distance $\sqrt2$, then undo the normalizations.

For a normalized correspondence $(x,y)\mapsto(u,v)$, add the two rows

$$\begin{bmatrix}-x&-y&-1&0&0&0&ux&uy&u\\0&0&0&-x&-y&-1&vx&vy&v\end{bmatrix}$$

to $A$. If $T_1,T_2$ normalize source and destination coordinates, denormalize with $H=T_2^{-1}H_nT_1$.

Algorithm 20.1.1
assert number_of_pairs >= 4
reject_repeated_or_nearly_collinear_configurations(pairs)
source, T1 = normalize_points(source_points)
target, T2 = normalize_points(target_points)
A = dlt_rows(source, target)
h = full_right_null_vector(A)  # retain the ninth vector for an 8-by-9 minimal system
H = inverse(T2) @ reshape3x3(h) @ T1
check_rank_and_projection_denominators(H)
H = refine_geometric_error(H, pairs)

Setting the bottom-right coefficient to one is safe only when that coefficient is not near zero. Its value depends on coordinates, not on a universal camera-angle threshold. Avoid normal equations when QR or SVD can solve the fit with better conditioning.

Four pairs determine a homography only in a nondegenerate configuration, with no three points collinear in either image. More well-distributed correspondences improve estimation, but a cluster in one corner can still extrapolate poorly. DLT minimizes algebraic error; refine using projected pixel residuals for a geometric fit.

Why four, and when fewer will do. The number four is not magic; it is just the eight degrees of freedom of a projective homography divided by the two equations each correspondence supplies. Assume less motion and you need fewer pairs, because every assumption you are willing to make removes degrees of freedom. A full projective map has 8 DOF → 4 pairs. Forbid perspective convergence (keep parallel lines parallel) and you drop to an affine map, 6 DOF → 3 pairs. Allow only translation, rotation, and a single scale (a similarity) and it is 4 DOF → 2 pairs. Adding translation to in-plane rotation and scale gives those 4 DOF; rigid translation-plus-rotation is 3 DOF → still 2 pairs (one is not quite enough); and pure translation is 2 DOF → one pair. The lesson recurs all through the book: a stronger model is cheaper to fit and more robust to noise, but only pays off when the assumption is actually true. Use the simplest transform the geometry allows, and no simpler. (For panoramas specifically, a known focal length turns the inter-image map into a 3-DOF rotation, fittable from as few as two correspondences. That is the basis of the rotation-only stitchers in the next chapter.)

20.1.6 Warping and assembling the panorama⧉

With $H$ in hand for each frame, we build the wide image. Pick one image's coordinate frame as the canvas, the reference, and for every other image, warp it into that frame using its homography (warping each frame one by one toward the reference). The union of the warped frames is the panorama; output pixels that no source image reaches remain invalid or transparent.

Inverse warping evaluates each covered output location in its source image. It avoids forward-splat sampling gaps, but cannot fill areas outside all source footprints. Carry a validity mask instead of using black as missing data. A corner bounding box is valid only when no projective pole crosses the source rectangle; check denominator signs and impose finite canvas limits before allocation. Resample with antialiasing appropriate to local minification (Chapter 11.1, Warping).

Two loose ends, both pointers. First, the warped frames overlap and will not match exactly (exposure, vignetting, and tiny misalignments differ between shots), so they must be merged seamlessly; that is the job of the blending section (feathered, two-scale, or Poisson). Second, warping everything onto a single flat reference plane stretches badly at very wide fields of view; cylindrical or spherical projections (and the stereographic "little planet") are the fix, covered later under other projections.

fig-pano-manual
Figure 20.1.5. Manual stitching, end to end (interactive). Click the same feature four times in each of two photographs; the homography from those four correspondences reprojects the second image into the first one's frame, the union bounding box sets a (bounded) output canvas, and a feathered blend merges them into one panorama. Upload your own overlapping pair. This is the whole manual pipeline, by hand.

20.1.7 Another application: document flattening and merging⧉

Everything above needed pure rotation because general scenes have depth. But there is a second route to the same homography, and it relaxes the rule entirely: a planar scene. If the scene is a single plane, a homography relates any two views of it, even when the camera translates, because a plane imposes one depth relationship across its whole surface, with no independent per-pixel depth to cause parallax. A plane photographed from any viewpoint maps to a plane by a homography. This is the planar twin of the rotation case.

Document rectification maps four detected page corners to a rectangle. Set its aspect ratio from known page dimensions or another justified constraint; arbitrary target dimensions can stretch the page. A homography cannot flatten a curved book page or remove lens distortion by itself (Figure 20.1.6).

The same machinery also handles document merging. To capture a document or whiteboard too big for one frame, shoot overlapping planar patches and stitch them with planar homographies, the identical pipeline as a panorama, except the homography is justified by the flat scene rather than by pure rotation. This is the basis of book scanning, mosaicing microscope slides, and tiling aerial or satellite images of locally flat ground.

Panoramas (rotation) and document rectification or merging (plane) are the same homography solve; only the geometric reason the homography is valid differs. Perspective-distortion correction (straightening a building's converging verticals) is the very same trick, and is developed alongside the warp machinery in Matching pixels across space and time.

fig-doc-flatten
Figure 20.1.6. Document flattening as the planar-scene case (interactive). A drawing photographed at an angle (left) appears as a keystoned quadrilateral; drag the four handles onto its corners and they become correspondences to a target rectangle. Solving for $H$ and warping yields a fronto-parallel, "scanned" page (right) with the rectangle restored and verticals upright, because the page is planar, so the homography holds even though the camera translated off to the side. Switch between three real children's drawings (a cat sketch, a lion on black paper, a framed dolphin) or upload your own page; only content on the page's plane rectifies exactly, so the surrounding wall stays distorted. Children's drawings photographed for this book.