Abandoned farmstead with fire ruin, Bad Wurzach (Germany) — 1,471 images, Mavic 2 Pro, nadir + oblique + facades (CC BY 4.0)

We are sharing one of our own datasets under CC BY 4.0. It turned out to be a nice stress test for ODM because it mixes nadir, oblique and low facade shots in one capture.

Download

Facts

Images 1,471 JPEG, DJI Mavic 2 Pro (Hasselblad L1D-20c), 5472 × 3648
Date 18 May 2023
Scene Abandoned farmstead: residential house, burnt-out barn, sheds, overgrown yard
Georeference GPS + DJI XMP (gimbal angles) in every image; no GCPs, no RTK
Capture Nadir and oblique flights (~21 m and ~87 m above take-off) plus low facade shots; 3 images (DJI100_0392–0394) look at the horizon

Privacy: licence plates, faces/heads and every vehicle larger than ~120 px are pixelated (detector plus manual review). Metadata (GPS, gimbal tags) is kept.

What we learned processing it (ODM 3.6)

  • Default settings gave a model with a flipped Z axis (“Negative GSD”) and DensifyPointCloud failures; sfm-algorithm: triangulation “worked” but everything was shifted.
  • What worked: keep the facade/oblique images (they stabilise the reconstruction), exclude only the 3 horizon images, OpenSfM align_method: orientation_prior (OpenSfM config; ODM has no CLI flag for it, we set it via a small patch in opendm/osfm.py), incremental SfM, no auto-boundary.
  • Result: 1,453 / 1,468 images in one reconstruction, reprojection error 0.83 px, GSD 0.60 cm, mean GPS deviation 1.69 m.

Attribution: “Bad Wurzach 2023 drone dataset © Bitblade (bitblade.io), CC BY 4.0”.

Happy processing — feedback and results welcome!

1 Like

Oh this is fantastic. Thank you. Do you think we need to consider making orientation_prior a default in ODM or exposing as an option?

I’ll do some testing on other datasets.

Thanks! I ran a control first, because our evidence was confounded: we only switched to orientation_prior after the default had failed, and in the same step we had also dropped the 3 horizon shots.

Control: stock opendronemap/odm:3.6.2, default alignment, the public images minus DJI100_0392–0394 (so the same 1,468 images as our good run), --feature-quality high --pc-quality high, stopped after openmvs:

default (align_method: auto) orientation_prior (our good run)
Images in reconstruction 1,451 / 1,468, 1 component 1,453 / 1,468, 1 component
Alignment chosen “well-conditioned, using naive 3D-3D alignment” orientation_prior
Mean GPS deviation (OpenSfM stats) 73.9 m (CE90 113 m, LE90 55 m) 1.69 m (CE90 1.41 m, LE90 2.61 m)
Median camera viewing direction (z) −0.04 (almost horizontal) −0.69 (looking down, as flown)
DensifyPointCloud 0 points, “no valid point-cloud for the ROI estimation” dense cloud, full pipeline finished

So with the horizon shots already removed, the default still fails. The relative reconstruction is fine (one component, 1,451 images). It’s the naive 3D-3D alignment that tilts it heavily against GPS, and densification then finds nothing. This time there was no “Negative GSD” warning, because the model is tilted, not upside down. So that check doesn’t catch every case.

My guess at why: most images are oblique, about 1,240 from ~21 m above take-off and ~150 from ~87 m, plus the low facade shots. The camera centres form a thin, uneven slab, and consumer GPS altitude error is a large share of its thickness. auto only tests whether the GPS positions are collinear, not whether they’re close to planar, so it picks naive.

Caveats: this is one dataset. Our good run used the original images (the public ones have plates/faces/vehicles pixelated) and our patched image, though no other patch there touches alignment. Also, orientation_prior alone wasn’t sufficient: a run with it but without the 50 low facade shots flipped too. Those shots help.

On default vs. option:

  • Since OpenSfM de3b1640 (April) orientation_prior fits the plane from the OPK angles, and ODM computes OPK from the DJI/Hasselblad gimbal XMP. So for gimbal drone data it no longer assumes nadir cameras.
  • Without OPK (phones, handheld) it falls back to align_orientation_prior: vertical, which would be wrong for horizontal imagery.

So I’d suggest:

  1. a flag like --sfm-align-method auto|naive|orientation_prior, default unchanged for now;
  2. maybe later auto → orientation_prior when every image has OPK and there are no GCPs, once more datasets are tested. Your tests on other data would be exactly what’s needed for that.

Happy to open a PR for (1). The control log is available if anyone wants it.

Yup. Just ran a test dataset through and it wasn’t sufficient.

I think the robust solution is to present an appropriate problem dataset upstream in OpenSfM, as this orientation challenge is usually present, just in less noticeable form.

I do have a smallish dataset which demonstrates it. If you also have something small which demonstrates it, maybe we can open an issue at opensfm/opensfm.