Which parameters control the Z-values in the point cloud?

I have 27 GCP with their corresponding Z-value, each of them present in at least three images. ODM generates a good orthophoto and a very dense point cloud.

The problem:
The generated Z-values in the point cloud are very different from those provided in the GCP file, even in the nearby areas of the GCPs.

The question
Which parameters should I tweak to obtain Z-values in the point cloud that are similar to those provided in the GCP file?

Hi @geofis, are you running the latest version of OpenDroneMap? A week ago we made changes to the GCP handling code (which affect elevation values).

Thanks @pierotofy.

I’m running the latest stable release, 0.3.1. I guess that to take advantages of the changes you mention, I should run the workflow from the master. I will give it a try, and then I let you know.

1 Like

I ran ODM from the master version and the Z-values are still incorrect. In fact, with the latest stable release, the results were better than with the master. I think that the problem has something to do with the distortion applied to the images. I use historical photos with large focal length and width, and I don’t have all the parameters to make a perfect transformation. I will try a new transformation to test again the toolchain, and then I post the results.

Hi there,

I run about 300 images (2x150 images per strip) covering 1,5 km of area of interest having around 30-35 ground control points acquired by Trimble augmented with RTX. I use some of them as tie points and the rest as GCPs. After the latest correction, the point cloud is within few centimeters off from what Trimble is reporting.

Are you sure the ODM is parsing the GCP file?


In response to @0x906: as far as I can tell, ODM is parsing the GCP file, because the orthophoto and the point cloud fit roughly in the area of interest, but with ODM master, horizontal errors can reach 10 meters or more, and in the vertical direction they are hundred of meters.

Returning to the problem of the wrong Z-values, I think that this issue has something to do with the undistorted versions of my images, or maybe it is because of their “little” overlap (60%). Since I’m using historical photos, I think that the software is expecting short focal length and narrow CCD width.

In order to improve the process, I transformed (again) the images using higher accuracy strategy which ensures that the principal point of photo one is located on the central pixel. With the new transformed images, ODM latest stable release (LSR, version 0.3.1) produces acceptable outputs, and those generated with the master are poor.

The following image shows an animation of the orthophoto and the point cloud (1.8 million points) generated with ODM master (Google Satellite in the background):

The animation shows that there are significant shifts between the orthophoto and the background. Also the point cloud is noisy and locally sparse.

To generate these outputs, I used the following sentence to run the toolchain:
./run.sh FOLDER --project-path PATHTOPROJECT --resize-to -1 --force-focal 152.929 --force-ccd 226.5 --orthophoto-resolution 1 --min-num-features 30000 --matcher-neighbor 14 --mesh-octree-depth 12 --texturing-keep-unseen-faces --texturing-skip-visibility-test --texturing-data-term area

I also edited the /SuperBuild/src/opensfm/opensfm/config.py file with these settings:
depthmap_method: BRUTE_FORCE
depthmap_resolution: 1280
depthmap_num_neighbors: 14
depthmap_num_matching_views: 2
depthmap_patchmatch_iterations: 3
depthmap_min_patch_sd: 1
depthmap_min_correlation_score: 0.7
depthmap_same_depth_threshold: 0.005
depthmap_min_consistent_views: 2
depthmap_save_debug_files: no

On the other hand, the following image shows the results from ODM LSR:

To generate these outputs, I used the same config.py configuration, the same images and the same gcp_list.txt file as in the master. I ran the toolchain with the following sentence:
./run.sh FOLDER --project-path PATHTOPROJECT --resize-to 5351 --force-focal 152.929 --force-ccd 226.5 --orthophoto-resolution 1 --min-num-features 30000 --matcher-neighbor 14 --mesh-octree-depth 12 --texturing-keep-unseen-faces --texturing-skip-visibility-test --texturing-data-term area

It is noticeable that in the LSR outputs, there are no accuracy issues between the orthophoto and the background. Also, the Z-values of the point cloud (>7 million points!) match pretty well with the heights of the reference source (the topo 50K). A scarce noise is present in some places (e.g. over the town), due to the printed information on the frames. In order to clean these outliers, I tested a workflow with PCL that worked efficiently.

I am still curious to know why ODM LSR outputs are better than those generated with the master?

Mm, hard to say. Is it possible for you to share the images and GCP file that you are using so that we can try to reproduce the issue?


The GCP file and the images are stored here.


1 Like

I can reproduce the problem. I found that a temporary fix could be to remove the “bundle_use_gcp” option from the opensfm pipeline:


            if tree.odm_georeferencing_gcp:
                #config.append("bundle_use_gcp: yes")
                io.copy(tree.odm_georeferencing_gcp, tree.opensfm)

I get the following result after applying this change:


This will require some further analysis… I’m not really familiar with how opensfm handles GCPs and why this is causing problems down the pipeline. I’ll see if I have some time next week.

Opened: https://github.com/OpenDroneMap/OpenDroneMap/issues/820

Thanks for your help.

I introduced the comment in line 100, and generated a good orthophoto. Nevertheless, the point cloud is still noisy and sparse.

Anyway, with PMVS, the point cloud fits better to the Z-values of the GCP.

@geofis did you make sure to completely delete all folders (except the images folder and the GCP file) before re-running the command? Just want to make sure that ODM is not skipping some steps because files are already stored.

Yes, I made sure that only images and gcp_list.txt files were in the folder before running ODM.

The following figure shows the point cloud generated with OpenSfM, using the master version:

I used the file version of /SuperBuild/src/opensfm/opensfm/config.py mentioned above:

This is the sentence I used to run ODM:
./run.sh ocoaodml44trials --project-path /home/jose/ODMProjects/ --resize-to -1 --force-focal 152.929 --force-ccd 226.5 --orthophoto-resolution 1 --min-num-features 30000 --matcher-neighbor 14 --mesh-octree-depth 12 --texturing-keep-unseen-faces --texturing-skip-visibility-test --texturing-data-term area

Also, I made a new test omitting the focal length and CCD width flags, and obtained a very similar point cloud:

I tried again using the default version of /SuperBuild/src/opensfm/opensfm/config.py. The point cloud has little noise:

Of course, points appeared only in areas with 3 overlapping images, which doesn’t cover the entire area of my project, and for me it is useless.

Changing to 3 depthmap_min_consistent_views in config.py, the point cloud resulted more dense and without gaps…

…but a closer analysis depicts that heights are more stable with PMVS than with OpenSfM (seems to produce a wavy pattern), as seen in this profile (green-PMVS, pink-OpenSfM), which makes me prefer the former:

I will keep the PMVS dense point cloud, because at least in my case (historical aerial photos), the outcomes are much better.

Thanks for your answers.

1 Like