diff --git a/docs/comparisons/cars.md b/docs/comparisons/cars.md new file mode 100644 index 0000000..a8a542c --- /dev/null +++ b/docs/comparisons/cars.md @@ -0,0 +1,150 @@ +# CARS vs ASP — SpaceNet UCSD WorldView-3 + +Compare DEMs produced by ASP and CARS on the same WorldView-3 stereo pair: + +- **ASP** (NASA Ames Stereo Pipeline) — processed in the [UCSD notebook](../examples/notebooks/worldview_spacenet_ucsd_stereo) +- **[CARS](https://github.com/CNES/cars)** (CNES open-source stereo pipeline) + +## About CARS + +CARS is an open-source Python tool developed by CNES (French Space Agency) for producing DSMs from satellite stereo imagery. Key features: + +- **Dense matching**: Uses [Pandora](https://github.com/CNES/Pandora) (Census cost + SGM) with multiple presets for urban, mountain, vegetation +- **Multi-resolution**: Coarse-to-fine processing (default 16x → 4x → 1x) progressively narrows disparity search range +- **Geometry**: Uses [Shareloc](https://github.com/CNES/shareloc) for RPC handling — reads RPCs directly from GeoTIFF metadata +- **Tiled architecture**: Processes data in tiles with configurable parallelism and per-worker memory limits — avoids the full-scene memory issues encountered with SETSM +- **No bundle adjustment** in the standard pipeline. Instead, CARS corrects epipolar grids using sparse SIFT tie points. Separate `cars-bundleadjustment` tool available as an optional extra. + +## Source Data + +Same WorldView-3 stereo pair as the [SETSM comparison](setsm): + +| Catalog ID | Date | Off-nadir | Image size | +|---|---|---|---| +| 1040010007A93700 | 2015-02-12 | 8.4° | 43008 × 46080 px | +| 1040010007CA4D00 | 2015-02-24 | 12.9° | 43008 × 46080 px | + +This is the same pair (`21deg_12d`, convergence 21.2°) used in the [scene-selection notebook](../examples/notebooks/worldview_spacenet_ucsd_stereo_scene_selection) and the [ASP processing notebook](../examples/notebooks/worldview_spacenet_ucsd_stereo). + +## Processing Approach: ROI on Full Images + +CARS supports two approaches for sub-scene processing: + +1. **`cars-extractroi`** — pre-crops images and writes adjusted RPCs as `.RPB` sidecar files +2. **`roi` config parameter** — uses full images for sparse matching / grid correction but only runs dense matching within the specified ROI + +We use approach 2 (`roi`) because full images give CARS more context for SIFT tie-point matching and epipolar grid correction, with no manual RPC adjustment needed. + +The ROI matches the ASP processing crop area (UCSD campus region, ~4 km × 4 km): + +``` +Lon: -117.262 to -117.219 +Lat: 32.854 to 32.890 +``` + +## Running CARS via Docker + +```bash +docker pull cnes/cars + +docker run --platform linux/amd64 --rm \ + --cpus 6 \ + -v /path/to/input_images:/input:ro \ + -v /path/to/output:/output \ + cnes/cars /output/config.yaml +``` + +:::{dropdown} Full configuration file (config.yaml) +:icon: file-code + +```yaml +input: + sensors: + left: + image: /input/1040010007A93700_P001.tif + right: + image: /input/1040010007CA4D00_P001.tif + roi: + type: FeatureCollection + features: + - type: Feature + properties: {} + geometry: + type: Polygon + coordinates: + - - [-117.262, 32.854] + - [-117.219, 32.854] + - [-117.219, 32.890] + - [-117.262, 32.890] + - [-117.262, 32.854] + +output: + directory: /output/results + resolution: 2.0 + epsg: 32611 + +orchestrator: + mode: multiprocessing + nb_workers: 2 + max_ram_per_worker: 1500 +``` + +Key parameters: +- `output.resolution: 2.0` — 2 m output to match ASP processing +- `output.epsg: 32611` — UTM 11N (same CRS as ASP DEM) +- `orchestrator.nb_workers: 2` — limit parallelism for 16 GB laptop +- `orchestrator.max_ram_per_worker: 1500` — 1.5 GB per worker +::: + +Expected outputs in `results/`: +- `dsm/dsm.tif` — DSM as GeoTIFF (float32) +- `dsm/image.tif` — Ortho-image +- `metadata.json` — Processing parameters and statistics + +:::{dropdown} Notes on configuration +:icon: light-bulb + +- **Vertical reference**: CARS defaults to EGM96 geoid heights. For comparison with ASP (ellipsoidal heights), set `geoid: false` in the output config or convert afterwards. +- **Matching preset**: Default is `census_sgm_default` (Census5, P1=8, P2=32). For urban areas, `census_sgm_urban` (Census11, P1=20, P2=80) may perform better. +- **Initial elevation**: Providing a coarse DEM via `input.initial_elevation.dem` narrows the disparity search range and speeds processing. +::: + +## Run Metrics + +| Metric | Value | +|---|---| +| Computation time | ~17 h 18 min | +| Peak memory | ~10.3 GB (hit CARS' `RAM available < 500 Mb` warnings near the end) | +| Docker `--memory` limit | 11 GB | +| Output DSM | 2017 × 2001 px, 2 m, EPSG:32611 + EGM96 | +| Output std dev (raw) | 134.6 m (inflated by edge blunders outside the 3 km comparison box) | +| Output std dev (3 km comparison crop) | 48.7 m | +| Convergence angle | 21.2° | + +CARS is much slower than SETSM on this laptop (17 h vs 20 min), primarily because Pandora's per-tile Census + SGM matching is done in pure Python multiprocessing with two workers at 1.5 GB each. The run reports `RAM available < 500 Mb` warnings during the final `texture / dsm / dsm_weights` passes but completes successfully. The raw DSM carries some edge blunders (min −321 m, max 1273 m) outside the canonical 3 km comparison area; inside the comparison crop the range collapses to approximately −200 m to +200 m with outliers concentrated at the seaward edge. + +## Hillshade Comparison + +::::{grid} 3 +:::{grid-item} +![Copernicus 30m](../examples/figures/ucsd-cop30m-hillshade.png) +**Copernicus 30m DEM** +::: +:::{grid-item} +![ASP 2m](../examples/figures/ucsd-asp2m-hillshade.png) +**ASP 2m DEM** +::: +:::{grid-item} +![CARS 2m](../examples/figures/ucsd-cars2m-hillshade.png) +**CARS 2m DEM** +::: +:::: + +CARS resolves the urban structure cleanly — buildings, streets, the I-5 freeway on the east, Mount Soledad terrain on the west — comparable to ASP in detail. Some speckle remains along the seaward edge where CARS' ROI extends beyond the stereo overlap. No tile-boundary artifacts. + +## References + +- [CARS repository](https://github.com/CNES/cars) +- [CARS documentation](https://cars.readthedocs.io) +- [Pandora dense matching engine](https://github.com/CNES/Pandora) +- [Shareloc geometry library](https://github.com/CNES/shareloc) diff --git a/docs/comparisons/index.md b/docs/comparisons/index.md new file mode 100644 index 0000000..25faec8 --- /dev/null +++ b/docs/comparisons/index.md @@ -0,0 +1,43 @@ +# Pipeline Comparisons + +Comparisons of ASP with other open-source stereo photogrammetry pipelines, using the [SpaceNet UCSD WorldView-3 example](../examples/notebooks/worldview_spacenet_ucsd_stereo) as a common test case. + +::::{grid} 1 +:gutter: 3 + +:::{grid-item-card} SETSM +:link: setsm +:link-type: doc + +Surface Extraction with TIN-based Search-space Minimization (Ohio State / PGC). +::: + +:::{grid-item-card} CARS +:link: cars +:link-type: doc + +CNES open-source stereo pipeline with Pandora dense matching. +::: + +:::: + +## Key Differences + +| Feature | ASP | CARS | SETSM | +|---|---|---|---| +| Language | C++ | Python + C++ (pybind11) | C++ | +| Dense matching | NCC, MGM, SGM, etc. | Pandora (Census + SGM) | TIN-based NCC | +| Bundle adjustment | Integrated (`bundle_adjust`) | Separate tool (optional) | None (RPC bias comp. only) | +| Memory management | In-process | Tiled, per-worker limits | Full image by default; sub-scene via `-boundary_*` flags | +| Parallelism | OpenMP threads | multiprocessing / Dask | OpenMP / MPI | +| Cropped processing | `mapproject` with crop window | ROI config or `cars-extractroi` | `-boundary_*` flags on full images | +| Install | Pre-built binaries | pip / Docker | Build from source | +| License | Apache 2.0 | Apache 2.0 | Apache 2.0 | + +```{toctree} +:maxdepth: 1 +:hidden: + +setsm +cars +``` diff --git a/docs/comparisons/setsm.md b/docs/comparisons/setsm.md new file mode 100644 index 0000000..fe6ba47 --- /dev/null +++ b/docs/comparisons/setsm.md @@ -0,0 +1,124 @@ +# SETSM vs ASP — SpaceNet UCSD WorldView-3 + +Compare DEMs produced by two open-source stereo photogrammetry pipelines on the same WorldView-3 stereo pair: + +- **ASP** (NASA Ames Stereo Pipeline) — processed in the [UCSD notebook](../examples/notebooks/worldview_spacenet_ucsd_stereo) +- **[SETSM](https://github.com/setsmdeveloper/SETSM)** (Surface Extraction with TIN-based Search-space Minimization) — Ohio State / Polar Geospatial Center + +Both pipelines accept raw satellite imagery with RPC camera models and produce gridded DSMs. + +## Source Data + +IARPA CORE3D SpaceNet UCSD dataset — two WorldView-3 panchromatic acquisitions: + +| Catalog ID | Date | Off-nadir | Image size | +|---|---|---|---| +| 1040010007A93700 | 2015-02-12 | 8.4° | 43008 × 46080 px | +| 1040010007CA4D00 | 2015-02-24 | 12.9° | 43008 × 46080 px | + +This is the same pair (`21deg_12d`, convergence 21.2°) used in the [scene-selection notebook](../examples/notebooks/worldview_spacenet_ucsd_stereo_scene_selection) and the [ASP processing notebook](../examples/notebooks/worldview_spacenet_ucsd_stereo). + +## Approach + +SETSM is open-source (Apache 2.0), pure C++ with no GPU requirement. We built and ran it via Docker to avoid host dependency conflicts. + +SETSM reads only `*.tif` and `*.raw` images, so the source NTFs must be converted up-front. Section 2.1.4 of the [SETSM User Manual](https://github.com/setsmdeveloper/SETSM/blob/master/SETSM_User_manual.pdf) provides the exact `gdal_translate` command: + +```bash +gdal_translate -q --config GDAL_CACHEMAX 2048 -ot UInt16 -co NBITS=16 \ + -co bigtiff=if_safer -co tiled=yes -co compress=lzw input.ntf output.tif +``` + +The DigitalGlobe NTFs use JPEG2000 internal compression, so the GDAL build doing the conversion needs a JP2 driver — ASP's bundled `gdal_translate` (e.g. `~/asp/dev/bin/gdal_translate`) ships with `JP2OpenJPEG`. The output TIFFs end up larger than the source NTFs (~2.4 GB each here) because LZW does not compress 11-bit panchromatic content as efficiently as JPEG2000. + +SETSM then works on those TIFFs with RPC camera models read from the DigitalGlobe XML metadata files (the XMLs live alongside the TIFFs and share the basename). Memory is the limiting factor on a laptop: + +- **Without sub-scene flags:** SETSM builds image pyramids for the entire scene by default. Two UInt16 images plus pyramids exceed 14 GB RAM and the container is OOM-killed (exit code 137) on a 16 GB machine. +- **With `-boundary_*` flags:** SETSM only reads and pyramids the subset of each image needed for the requested output extent, so memory scales with the output area, not the input image size. + +:::{dropdown} Docker build details +:icon: terminal + +```bash +git clone https://github.com/setsmdeveloper/SETSM.git +cd SETSM + +docker build --platform linux/amd64 -t setsm -f- . <<'DOCKERFILE' +FROM ubuntu:24.04 AS builder +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ make git \ + libgeotiff-dev libtiff-dev libproj-dev libjpeg-dev zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* +COPY . /opt/SETSM +WORKDIR /opt/SETSM +RUN make INCS="-I/usr/include/geotiff" + +FROM ubuntu:24.04 +RUN apt-get update && apt-get install -y --no-install-recommends \ + libgeotiff5 libgomp1 libtiff6 libproj25 \ + && rm -rf /var/lib/apt/lists/* +COPY --from=builder /opt/SETSM/setsm /usr/local/bin/setsm +COPY --from=builder /opt/SETSM/default.txt /usr/local/share/setsm/default.txt +WORKDIR /data +ENTRYPOINT ["sh", "-c", "cp /usr/local/share/setsm/default.txt /data/default.txt 2>/dev/null; exec setsm \"$@\"", "--"] +DOCKERFILE +``` + +Multi-stage build — the final image contains only the `setsm` binary and runtime libraries. The `default.txt` config file is bundled and auto-copied at runtime (SETSM requires it in the working directory). +::: + +## Run + +```bash +docker run --platform linux/amd64 --rm --name setsm_boundary \ + --memory 11g --cpus 6 \ + -v /path/to/data:/data -w /data setsm \ + -image 1040010007A93700_P001.tif -image 1040010007CA4D00_P001.tif \ + -outpath /data/results -outres 2 -mem 10 -minH 0 -maxH 300 \ + -boundary_min_X 476000 -boundary_min_Y 3635600 \ + -boundary_max_X 479000 -boundary_max_Y 3638600 \ + -projection utm +``` + +The boundary defines a 3 km × 3 km UTM 11N area matching the ASP processing extent. + +| Metric | Value | +|---|---| +| Computation time | ~20 min | +| Peak memory (SETSM-reported) | 2.72 GB | +| Docker `--memory` limit | 11 GB | +| Output DEM | 1500 × 1500 px, 2 m, EPSG:32611 | +| Output std dev | 39.6 m | +| Convergence angle | 21.2° | + +### Hillshade Comparison + +::::{grid} 3 +:::{grid-item} +![Copernicus 30m](../examples/figures/ucsd-cop30m-hillshade.png) +**Copernicus 30m DEM** +::: +:::{grid-item} +![ASP 2m](../examples/figures/ucsd-asp2m-hillshade.png) +**ASP 2m DEM** +::: +:::{grid-item} +![SETSM 2m](../examples/figures/ucsd-setsm2m-hillshade.png) +**SETSM 2m DEM** +::: +:::: + +SETSM resolves the same urban structure as ASP — buildings, streets, and the campus / Mount Soledad topography are all clearly visible. The SETSM hillshade is somewhat speckled compared to ASP's, but the underlying geometry is recovered. No tile-boundary artifacts. + +:::{dropdown} Additional notes +:icon: note + +- SETSM's user manual warns against `-seed `: *"We caution that it is better to not use a seed DEM if possible, as it can only negatively impact the quality of the SETSM DEM."* +- The run did not produce `results_hillshade.tif`; the hillshade above was generated from `results_dem.tif` with a matplotlib `LightSource` shader. +::: + +## References + +- [SETSM repository](https://github.com/setsmdeveloper/SETSM) +- [SETSM user manual](https://github.com/setsmdeveloper/SETSM/blob/master/SETSM_User_manual.pdf) +- Noh & Howat (2015), "Automated stereo-photogrammetric DEM generation at high latitudes: Surface Extraction with TIN-based Search-space Minimization (SETSM) validation and demonstration over glaciated regions", *GIScience & Remote Sensing*, 52(2), 198-217. diff --git a/docs/index.md b/docs/index.md index 56371bb..58da450 100644 --- a/docs/index.md +++ b/docs/index.md @@ -49,6 +49,13 @@ Modular usage examples by sensor type. Full Python API documentation. ::: +:::{grid-item-card} Pipeline Comparisons +:link: comparisons/index +:link-type: doc + +ASP vs SETSM, CARS, and other stereo pipelines. +::: + :::{grid-item-card} Contributing :link: contributing :link-type: doc @@ -82,6 +89,7 @@ cli/index examples/index examples/reports API Reference +comparisons/index contributing changelog ``` diff --git a/notebooks/figures/ucsd-asp2m-hillshade.png b/notebooks/figures/ucsd-asp2m-hillshade.png new file mode 100644 index 0000000..5cacebc Binary files /dev/null and b/notebooks/figures/ucsd-asp2m-hillshade.png differ diff --git a/notebooks/figures/ucsd-cars2m-hillshade.png b/notebooks/figures/ucsd-cars2m-hillshade.png new file mode 100644 index 0000000..01053e1 Binary files /dev/null and b/notebooks/figures/ucsd-cars2m-hillshade.png differ diff --git a/notebooks/figures/ucsd-cop30m-hillshade.png b/notebooks/figures/ucsd-cop30m-hillshade.png new file mode 100644 index 0000000..1f872bc Binary files /dev/null and b/notebooks/figures/ucsd-cop30m-hillshade.png differ diff --git a/notebooks/figures/ucsd-setsm2m-hillshade.png b/notebooks/figures/ucsd-setsm2m-hillshade.png new file mode 100644 index 0000000..f7e2df5 Binary files /dev/null and b/notebooks/figures/ucsd-setsm2m-hillshade.png differ