Thanks for ODM! I've been running a very cheap toy drone (Holy Stone HS156, 99 g) through the pipeline as part of UN Open GIS Initiative DWG7 (context: UNopenGIS/7#921) and hit a performance problem worth reporting.
How did you install ODM? (Docker, installer, natively, ...)?
Docker (opendronemap/odm:latest), reproduced on 3.6.2.
What is the problem?
create_dem() (opendm/dem/commands.py#L68) rasterizes the raw bounding box of the point cloud, so a few gross SfM/MVS outliers (common on weak-baseline / low-overlap / non-nadir captures) can inflate the raster by orders of magnitude. The cost scales with extent, not point count.
Real example (31 geotagged images, weak baseline): the filtered cloud spans 5431 × 6515 m although the real scene is ~76 × 79 m (1st to 99th percentile), giving a ~39-gigapixel DSM raster. On 3.6.2, create_dem takes ~604 s (gdal_translate 193 s + fastrasterfilter 324 s on the inflated raster; renderdem is 5.5 s on LAZ but 446 s on the PLY that odm_meshing actually uses). A comparable 25-image set (27 MP raster) finishes in seconds despite a near-identical point count.
renderdem's maxTiles guard is disabled for geotagged photos (odm_meshing.py#L63, odm_dem.py#L79). This looks like the same "weak reconstruction, untrustworthy scale" family as #2054, on the DEM/mesh side.
How can we reproduce this?
Self-contained script (uses only numpy/pdal/opendm from the image); it builds an 80 × 80 m scene plus a few flyers a couple of km away and runs the real create_dem() with and without them:
docker run --rm -v "$PWD":/w --entrypoint python3 \
opendronemap/odm:latest /w/reproduce_dem_outlier_blowup.py
On 3.6.2: WITH flyers (0.015% of points) → 3321 MP, create_dem 69.7 s; WITHOUT → 2.6 MP, 0.6 s.
Script and a 3 MB real-cloud sample: http://z.yuiseki.net/static/tmp/github/odm/ (note: renderdem alone on LAS/LAZ skips empty tiles quickly, so drive the full create_dem chain).
What should be the expected behavior? ...
A few outliers should not blow up the raster.
Proposed fix: in create_dem(), crop the cloud to a robust percentile window before renderdem, but only when the raw extent is both far larger than the robust one and large in absolute terms (quickinfo is checked first, so normal data is never even sampled).
Measured: create_dem 604 → 3.5 s, odm_meshing 1225 → 27 s, output mesh essentially unchanged; no false positives on 800 m uniform / transect / L-shaped surveys.
Trade-off: two genuinely separate survey areas km apart could be cropped (guarded and warned; normally handled by --split).
Reference implementation with a unit test: yuiseki/ODM:fix/dem-outlier-safe-extent . Happy to open a PR.
AI disclosure
Per CONTRIBUTING (Use of AI): I used an AI coding assistant to help profile the pipeline, take the measurements above, and draft this report and the reference branch. I directed the investigation and verified the numbers and behavior myself. Happy to discuss.
Thanks for ODM! I've been running a very cheap toy drone (Holy Stone HS156, 99 g) through the pipeline as part of UN Open GIS Initiative DWG7 (context: UNopenGIS/7#921) and hit a performance problem worth reporting.
How did you install ODM? (Docker, installer, natively, ...)?
Docker (
opendronemap/odm:latest), reproduced on 3.6.2.What is the problem?
create_dem()(opendm/dem/commands.py#L68) rasterizes the raw bounding box of the point cloud, so a few gross SfM/MVS outliers (common on weak-baseline / low-overlap / non-nadir captures) can inflate the raster by orders of magnitude. The cost scales with extent, not point count.Real example (31 geotagged images, weak baseline): the filtered cloud spans 5431 × 6515 m although the real scene is ~76 × 79 m (1st to 99th percentile), giving a ~39-gigapixel DSM raster. On 3.6.2,
create_demtakes ~604 s (gdal_translate 193 s + fastrasterfilter 324 s on the inflated raster; renderdem is 5.5 s on LAZ but 446 s on the PLY thatodm_meshingactually uses). A comparable 25-image set (27 MP raster) finishes in seconds despite a near-identical point count.renderdem's
maxTilesguard is disabled for geotagged photos (odm_meshing.py#L63, odm_dem.py#L79). This looks like the same "weak reconstruction, untrustworthy scale" family as #2054, on the DEM/mesh side.How can we reproduce this?
Self-contained script (uses only numpy/pdal/opendm from the image); it builds an 80 × 80 m scene plus a few flyers a couple of km away and runs the real
create_dem()with and without them:docker run --rm -v "$PWD":/w --entrypoint python3 \ opendronemap/odm:latest /w/reproduce_dem_outlier_blowup.pyOn 3.6.2: WITH flyers (0.015% of points) → 3321 MP, create_dem 69.7 s; WITHOUT → 2.6 MP, 0.6 s.
Script and a 3 MB real-cloud sample: http://z.yuiseki.net/static/tmp/github/odm/ (note:
renderdemalone on LAS/LAZ skips empty tiles quickly, so drive the fullcreate_demchain).What should be the expected behavior? ...
A few outliers should not blow up the raster.
Proposed fix: in
create_dem(), crop the cloud to a robust percentile window before renderdem, but only when the raw extent is both far larger than the robust one and large in absolute terms (quickinfo is checked first, so normal data is never even sampled).Measured:
create_dem604 → 3.5 s,odm_meshing1225 → 27 s, output mesh essentially unchanged; no false positives on 800 m uniform / transect / L-shaped surveys.Trade-off: two genuinely separate survey areas km apart could be cropped (guarded and warned; normally handled by
--split).Reference implementation with a unit test: yuiseki/ODM:fix/dem-outlier-safe-extent . Happy to open a PR.
AI disclosure
Per CONTRIBUTING (Use of AI): I used an AI coding assistant to help profile the pipeline, take the measurements above, and draft this report and the reference branch. I directed the investigation and verified the numbers and behavior myself. Happy to discuss.