mapillary / OpenSfM

Open source Structure-from-Motion pipeline
https://www.opensfm.org/
BSD 2-Clause "Simplified" License
3.4k stars 858 forks source link

Uncertainty Priors for GCPs and Shot Position in Bundle Adjustment #590

Open valschmidt opened 4 years ago

valschmidt commented 4 years ago

The "Ceres" bundle adjustment solver used by OpenSfM has the ability to handle full uncertainty priors of each term. But it seems to me they are hard coded in OpenSfm and so not available to users. I'm curious if they might be added.

The benefit would be that the results of the SfM solution could be quantified more meaningfully (with the posterior), and users could properly weight the relative uncertainty of their GCPs and camera navigation to get more globally accurate solutions.

For example, one should be able to specify the uncertainty uncertainty for GCP data. But in the code, specifically, here: https://github.com/mapillary/OpenSfM/blob/b397e71fed94f88a9dbfa0e51a519569db6b9fba/opensfm/reconstruction.py#L150)

        ba.add_point_position_world(point_id, point.coordinates, 0.1,
                                    point_type)

...the uncertainty in the GCPs are hard coded to 0.1. Ideally a user could instead specify the GCP uncertainty in the GCP data file and it would be populated here.

To make the GCP uncertainty meaningful, it probably means one would have to get the uncertainty estimate right for the shot positions too - at least reasonable values or manually specifiable values. Currently it looks like GPS "dop" is used as a proxy for uncertainty. [I didn't immediately see what happens if DOP isn't available in the exif data.] In any event, dilution of precision is a scaled value that is more representative of the geometry of the satellite constellation for the fix, and while related to the fix uncertainty is not really the uncertainty itself. So what to do?

One solution I have seen elsewhere is sigma = sigma_o + DOP * sigma_o where sigma_o is a nominal value based on the fix type. This could be gleaned from the "GPS horizontal positioning error" exif field, but I don't know how widely that field is populated and there's no standard to know whether this is 1-sigma, 2-sigma or something else. My mobile phone populates it (10 m on the one image I checked), on a GoPro Hero 4 it is not populated at all. Notably DOP is not specified on either my phone or a GoPro. Perhaps DOP is typically populated on Drone imagery?

YanNoun commented 3 years ago

Hi @valschmidt ,

GPS std. dev. is fetched by reading the GPSDOP EXIF tag of the images during the extract_metadata step. Alternatively, the user can specify it by providing the EXIF value {"gps" : { "dop": in the exif_overrides.json file.

Regarding GCPs, yes, the std. dev. is hardcoded and it should be possible for the user to input it, we're going to add it as a feature.

Yann