Two live demos. Demo 1 uses optical imagery (Sentinel-2, 10 m visible-light) to track sand-dune migration over six years and forecast when each dune will reach a pipeline. Demo 2 uses sub-metre radar imagery (synthetic-aperture radar, day/night, cloud-piercing) for a deep-zoom time-lapse of an active industrial site. Both demos run on the same modular pipeline — drop in a new AOI polygon and a new STAC catalog and the analysis carries over.
Six years of monthly optical imagery over the Mauritanian Atlantic dune field (21.5°N, 16.7°W). We detect every individual barchan in every frame, stitch them into trajectories with a multi-target tracker, fit a velocity vector per dune with ordinary least squares, and project each forward in time. The viewer lets you draw a pipeline on the map and asks the system to predict — dune by dune — when and where each one will reach the line.
Cloud-free optical scenes, Jan 2020 → Apr 2026 over a ~45 × 45 km AOI.
Individual barchans linked across ≥ 6 monthly observations spanning a median of 1.6 yr within the 6-year window.
Direction overwhelmingly S/SSW — matches the prevailing trade-wind regime.
Kinematic extrapolation per dune. Useful at ≤ 10-yr horizons; longer is illustrative — dunes accelerate as they shrink and wind direction varies ±20° year-to-year.
|ΔA|/max < 0.3). Tracks surviving ≥ 6 observations across ≥ 1 year are kept.(vx, vy) in m / day, plus a heading and R².t = 0 are skipped.Straightness = ‖net displacement‖ / cumulative path length, on a 5-month smoothed trajectory. 1.0 = perfectly linear motion. Near 0 = wandering (the matcher kept hopping between neighbouring dunes). Wind-direction-agnostic — it doesn't assume the SSW wind.
R² = quality of the linear velocity fit. Low R² means residuals are large compared with the regression line.
Min observations = how many monthly samples a dune must have to count. The default (6) drops short-lived tracks.
Future prediction shifts each dune forward at its measured 2020-2026 velocity. Uncertainty grows roughly with √time, so very long horizons are illustrative only.
Raise the filters for strict / cleanest tracks; lower them to see every candidate. Predictions update instantly.
Track-level distributions on the unfiltered set of 1 274 trajectories:
Filter survival. Default thresholds (S ≥ 0.7, R² ≥ 0.4, n ≥ 6) retain ~660 tracks. Strict (S ≥ 0.9, R² ≥ 0.8) retains 169. Stricter filtering raises the median rate (the dropped tracks were disproportionately near-stationary mismatches), which is the expected behaviour of a quality filter.
Known gaps. We have not yet performed manual ground-truth digitisation in Google Earth Pro for an independent error measurement; the published 13–29 m/yr SSW range for the same region is our external sanity check rather than a per-dune validation. Per-dune velocity confidence intervals from the OLS fit (Var(β̂) = σ²(X⊤X)−1) are computable but not yet surfaced in the viewer.
56 sub-metre SAR frames over Telfer (Western Australia), one of Australia's largest gold-mining complexes. Radar sees through cloud and dust day or night, so we can monitor pit expansion, haul-truck traffic, tailings-dam growth, and equipment movement — features invisible to optical sensors when the weather is poor and untrackable after dark. The viewer stitches every frame into a tile pyramid that smoothly zooms from the full ~6.8 km AOI crop down to individual vehicles.
Sub-metre stripmap frames at 3-day cadence over 178 days. AOI crop 16 583 × 16 450 px at 0.41 m / px (~6.8 × 6.7 km).
Tile pyramid built with libvips — same UI as gigapixel deep-zoom viewers.
Per-tile shift-tolerant block matching + amplitude log-ratio. Robust to speckle.
Dense change field rendered as drifting particles — wind-map metaphor for change.
dzsave to build a Deep-Zoom-Image pyramid: 512-px JPG tiles at quality 85, 15 zoom levels. The viewer pulls only the tiles it needs at the current zoom and viewport — bandwidth per pan/zoom action is bounded by viewport size, not by scene size.cv2.matchTemplate with TM_CCOEFF_NORMED) on a sliding ±6 px window finds the best-fit local shift before comparing radiometry.|mean(log A) − mean(log B)| per 64-px tile. The log domain is natural for SAR: it converts multiplicative speckle into additive noise and makes the metric symmetric under bright/dark inversion. We subtract the per-pair median to remove global radiometric drift.Why SAR, not optical, for industrial monitoring. Radar backscatter depends on surface roughness and dielectric properties, not illumination — so a 6 a.m. winter pass and a 1 p.m. summer pass produce comparable images. Optical comparisons are confounded by sun angle, cloud cover, dust plumes, and seasonal vegetation. For a 24/7 operational site, SAR is the only modality that gives a regular baseline independent of weather and daylight.
Direct transfer to pipeline-corridor monitoring. The same processing chain — sub-metre stripmap acquisitions, NCC co-registration, log-ratio change with per-pair drift normalisation, particle-flow visualisation — applies unchanged to a Saudi pipeline right-of-way. At 3-day cadence it would surface dune-crest movement onto the alignment, third-party encroachment on the easement, new excavation activity, and surface-deformation patterns indicative of subsidence — all in conditions where optical, ground crews and aerial overflights are limited (night, dust storms, restricted-access terrain).
Both demos run on the same modular pipeline. Swap the AOI, the date range, and the sensor — the analysis carries over. The processed outputs (GeoJSON trajectories, tile pyramids, scene manifests) are pre-computed and rendered client-side, so the viewers themselves are static assets.
STAC-API query (Element-84 Earth-Search, ASF) by AOI polygon
and date interval, filtered on eo:cloud_cover for
optical and orbit geometry for SAR.
Read only the AOI tiles from each cloud-optimised GeoTIFF via
GDAL VSI + range-GET — gigabytes saved per scene
versus a full download.
rasterio.WarpedVRT warps every scene to Web
Mercator at the analysis resolution. One CRS for detection,
visualisation, and overlays — zero offset between layers.
Optical: per-frame percentile threshold +
skimage.measure.label connected components.
SAR: NCC co-registration via cv2.matchTemplate +
log-ratio per tile with per-pair median normalisation.
Greedy nearest-neighbour tracker with area-consistency gating. Per-axis OLS regression of UTM coords vs time per trajectory, returning v = (vx, vy), heading and R².
Linear projection p̂(t) = p0 + v · t. Sand-burial check by point-to-segment distance against a user-drawn polyline, sampled in 0.1-yr steps within a 100-yr horizon.
The core of the pipeline reduces to a handful of well-posed numerical operations — each one a standard tool from image processing, statistical estimation, or computational geometry. Display-side smoothing kernels and per-pair median normalisations are omitted here for brevity but are documented in the source.