Feed in two overlapping satellite images that carry RPC sensor models and the in-process pipeline extracts a dense Digital Surface Model: pure-C# RPC triangulation does the photogrammetry, a pluggable OpenCV StereoSGBM sidecar does the dense matching, and the produced height map auto-registers as both a served COG imagery layer and a terrain DemSource so viewshed, line-of-sight, and slope analysis consume it immediately. No cloud, no per-tile wait.
Seven stages run as an async job you poll — from RPC extraction through a math-correct triangulation that fixes height by minimizing the two-image reprojection residual.
.rpc/.rpb sidecar.# probe the matcher sidecar GET /api/stereo/capabilities → { matcher:{name,available}, pipeline:[…] } # start a stereo → DSM job POST /api/stereo/dsm { "leftCogId":"wv3-left", "rightCogId":"wv3-right", "options":{"HeightMax":9000} } → { "jobId":"a1b2c3…" } # poll → produced DSM GET /api/stereo/jobs/{jobId} → { "status":"succeeded", "dsmCogId":"ate-dsm-a1b2", "demSourceId":"ate-dsm-a1b2", "validPixelFraction":0.83 }
The triangulator implements the standard RPC forward-intersection (Grodecki & Dial 2003): a 1-D height search that projects a candidate ground point into both images and minimizes the combined reprojection RMS — the math that fixes elevation from two rays.
At each candidate height the reprojection residual is measured in both images; a coarse sweep brackets the minimum, golden-section refines to 0.05 m convergence. The output height is the residual minimum.
At the winning height, a single Newton step on (lon, lat) against the left image's Jacobian nudges the ground point onto the left ray — the least-squares intersection of the two RPC pencils.
The triangulator is covered by pure-math tests: a synthetic parallax pair recovers a known height, the reprojection RMS is zero at the exact ground point and grows for wrong heights, and the rectifier homography round-trips through its inverse.
The compute-heavy matching step is decoupled behind IMatcherStrategy. The default ships as a capability-gated Python/OpenCV sidecar; a future pure-C# Semi-Global Matching engine drops in with zero service or route changes.
A reference Python script (stereo_matcher.py) shells OpenCV's Semi-Global Block Matching. Three-tier resolve: explicit config → PATH scan for python → bundled runtimes/win-x64/stereo/. Clear 503 + install hint when absent.
The sidecar contract is two rasters in → one Float32 disparity GeoTIFF out. Point Stereo:MatcherScript at any matcher (a custom SGM build, a research model) and it runs.
A native Hirschmüller SGM implementation will plug in behind IMatcherStrategy — same shape as the SAR local-vs-cloud InSAR backends. No Python dependency at all when it lands.
The triangulation math, the orchestration, the DSM write, and the dual registration are all pure C#. Only the dense-matching step needs the optional sidecar.
Pair it with IMINT exploitation, virtual mosaic, and viewshed / line-of-sight for a complete exploitation loop.
Get Started