Skip to content
Back
Computer vision

360° Spherical Panorama Stitching

Turns one handheld phone sweep into a 360° panorama you can walk around in a browser.

My partBuilt solo

In short

A CPU-only Python and OpenCV pipeline that turns handheld phone video or stills into an equirectangular panorama and generates a Three.js viewer.

What it is
A CPU-only Python and OpenCV pipeline that turns handheld phone video or stills into an equirectangular panorama and generates a self-contained Three.js viewer.
Why it matters
General-purpose stitchers hide the geometric decisions behind a single call, which makes it hard to explain why a panorama tilts, ghosts, or drifts under real handheld capture.
My part
I built the pipeline, the viewer, the tests, and the technical documentation on my own.

Step by step

  1. 1

    Extract

    Frames are pulled from a phone video by interval, count, frame rate, or measured motion. Camera intrinsics come from EXIF when available, otherwise from an explicit field of view or calibration file.

  2. 2

    Match

    ORB features are matched between adjacent frames, filtered with Lowe’s ratio test, and validated by RANSAC. If an adjacent pair fails, the matcher tries across the gap and interpolates the missing step rather than silently discarding the frame.

  3. 3

    Rotate

    The relative rotation is recovered from R = K⁻¹HK under a pure-rotation model. Numerical noise means the matrix is rarely a perfect rotation, so singular-value decomposition projects it back onto the rotation manifold before chaining.

  4. 4

    Warp

    Each source frame is inverse-warped onto an equirectangular canvas. Each output pixel is a world direction; that direction is rotated into the camera, projected onto the image plane, and sampled.

  5. 5

    Smooth

    A moving average over the chained global rotations damps per-pair pitch and roll wobble. It is deliberately simple: not bundle adjustment, loop closure, or exposure matching.

  6. 6

    View

    The final 4096 × 2048 panorama is served through a self-contained Three.js viewer that makes the recovered geometry directly inspectable in a browser.

Results

309
Sample frames
phone video, single handheld sweep
333°
Recovered sweep
from a horizontal pan
921
Median RANSAC inliers
per adjacent pair
15 of 308
Interpolated pairs
recovered across a gap
36.9%
Sphere imaged
phone-height horizontal band
4096 × 2048
Output resolution
equirectangular
~2 minutes
End-to-end time
Ryzen 7 5800H, CPU only
13.5×
Pitch wobble reduction
temporal smoothing, on the sample run
5.2×
Roll wobble reduction
temporal smoothing, on the sample run

From the project

Full equirectangular panorama reconstructed from a handheld phone sweep of an interior room.
Equirectangular panorama recovered from a 309-frame phone sweep. 4096 × 2048 output; 36.9% of the sphere imaged.
A single extracted phone-video frame that becomes an input to the pipeline.
Stage 1 — frame extraction.
A pair of adjacent frames with ORB feature matches drawn between them.
Stage 2 — ORB matches surviving Lowe’s ratio and RANSAC.
A mosaic of intermediate stitched frames laid onto the equirectangular canvas.
Stage 3 — chained per-pair rotations before smoothing.
Side-by-side comparison of the panorama with and without temporal smoothing.
Smoothing comparison — long horizontal edges before and after.
The recovered panorama shown as a horizontal band, illustrating incomplete spherical coverage.
The captured band is only about 37% of the full sphere.
For engineersHow it is built, its limits, and its keywords.

How it works

Frames are extracted, matched with ORB features and RANSAC, related by homography under a pure-rotation camera model, projected back onto a sphere, and rendered in a browser viewer. Temporal smoothing damps the pitch and roll wobble left after per-pair estimation.

Limits

  • Pure-rotation camera model — translation while sweeping introduces parallax that no homography can explain.
  • A phone-height horizontal sweep sees a band around the viewer, so the poles are never captured; filling is not reconstruction.
  • Blank walls and repeated textures weaken ORB matching and can force interpolation.
  • No bundle adjustment or global loop closure; drift is damped rather than corrected.
  • No exposure matching; brightness changes remain visible across seams.

Keywords

  • panorama stitching
  • equirectangular projection
  • OpenCV
  • ORB features
  • RANSAC
  • temporal smoothing
  • Three.js viewer

Read the write-up →