10000 Pose Prior based Incremental Mapper by ferreram · Pull Request #2660 · colmap/colmap · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Pose Prior based Incremental Mapper #2660

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 55 commits into from
Sep 25, 2024
Merged

Conversation

ferreram
Copy link
Contributor

This PR adds the possibility to apply the Incremental Mapper pipeline while using position priors taken from the database. The prior position can be either in geographic coordinates or in cartesian coordinates. The position priors are used during the global BA only. For now, this prior based pipeline is only accessible through command line. A unit test has been added.

More is to come (add python bindings, prior based BA controller, possibility to setup priors from a file instead of through the database, python scripts to populate the database with priors, etc...) but I'd like to ensure that you are already okay with the current state of this PR before diving further.

Copy link
Member
@sarlinpe sarlinpe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for this contribution and sorry that it took me so long to look at it. This is very exciting! Did you test this on real data and could you share a sample of such data?

@sarlinpe sarlinpe requested a review from ahojnnes August 14, 2024 08:38
@ferreram
Copy link
Contributor Author

@sarlinpe thanks for your reply! I have a sample dataset of real data here acquired with a UAV with photos having GPS in the EXIF metadata here: https://filesender.renater.fr/?s=download&token=0418e1d0-ed8d-4bd4-89ec-e9f0b7772fe7.

Timer timer;
timer.Start();

if (NumPosePriors() < 3) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess this is only valid for when only having position based priors.

Conceptually, it feels like the database cache should at most warn but not produce an error in this case. I would have expected the incremental mapper to error out in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are completely right. I have modified it so that it only returns false if there is no prior in the database.


options.mapper->use_prior_position = true;

options.AddDefaultOption("set_database_priors_covariance",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the following maybe a more intuitive option name? If I understand correctly, if this is 67F4 false, then the covariance is read from the database?

Suggested change
options.AddDefaultOption("set_database_priors_covariance",
options.AddDefaultOption("overwrite_priors_covariance",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me 👍

Yes for now, the covariance is always read from the database but enabling the option overwrites the current state of the priors covariance.
I am planning to later add more ways for setting up the priors covariance (python / c++ scripts to set it from a file and maybe also a button in the database_widget).

Copy link
Contributor
@ahojnnes ahojnnes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great effort. I left another round of mostly "nit" comments. After this, the PR looks good to me and we can merge from my perspective. Thank you very much!

@sarlinpe sarlinpe self-requested a review September 25, 2024 09:29
@ahojnnes ahojnnes enabled auto-merge (squash) September 25, 2024 09:48
@ahojnnes ahojnnes merged commit 17f9e66 into colmap:main Sep 25, 2024
16 checks passed
@B1ueber2y
Copy link
Contributor

No tests were added for PositionPriorErrorCostFunction. Do you plan to add it in the future? : )

@ferreram
Copy link
Contributor Author

@B1ueber2y I wanted to do it and then forgot... I have just made a PR with test for PositionPriorErrorCostFunctor!

@ahojnnes
Copy link
Contributor

@ferreram Thank you!

@mattiasmar
Copy link

Is there a pycolmap interface for the pose_prior_mapper functionality?

@sarlinpe
Copy link
Member

Yes

m.def("create_pose_prior_bundle_adjuster",
CreatePosePriorBundleAdjuster,
"options"_a,
"prior_options"_a,
"config"_a,
"pose_priors"_a,
"reconstruction"_a);

@mattiasmar
Copy link
mattiasmar commented Nov 28, 2024

May I ask for example on how to use this interface?

Until recently my flow looked like this:


1. rec = pycolmap.Reconstruction()
2. define camera instances: pycolmap.Camera 
3. define images (camera poses + image paths): 
  * im = pycolmap.Image(image_name, [], cam_from_worldinv, camera_id, image_id)
  * rec.add_image(im)  (repeat for all images...)
4. Extract and Match features (with HLOC):    
     4.a extract_features.main(...)
     4.b match_features.main(...)
5. Perform triangulation using the existing camera poses
    triangulation.main(
        reference_model=reconstruction_path,
        sfm_dir = sfm_path,
        image_dir=Path(output_dir),
        pairs=sfm_pairs,
        features=features_path,
        matches=matches_path,
        skip_geometric_verification = True
    )
 final_reconstruction = pycolmap.Reconstruction(sfm_path)
 **pycolmap.bundle_adjustment(final_reconstruction, options)**

A) With the pycolmap.create_pose_prior_bundle_adjuster how would the above flow change?
B) Is this a correct definition of a PosePrior instance?

pose_prior = pycolmap.PosePrior()
*Set the position and orientation priors
pose_prior.position = np.array([1.0, 2.0, 3.0], dtype=np.float64)
pose_prior.orientation = np.array([0.0, 0.0, 0.0, 1.0], dtype=np.float64)  # Quaternion, scalar first

C) Would the pose_prior_bundle_adjuster be executed by calling "solve" and where would results be stored?

pose_prior_bundle_adjuster = pycolmap.create_pose_prior_bundle_adjuster(
    options=bundle_adjustment_options,
    prior_options=pose_prior_bundle_adjustment_options,
    config=bundle_adjustment_config,
    pose_priors=pose_priors,
    reconstruction=reconstruction
)
pose_prior_bundle_adjuster.solve()

@ahojnnes
Copy link
Contributor

A) You would like perform a pose prior based bundle adjustment after your call to triangulation. You may want to alternative a few rounds of (re-)triangulation and bundle adjustment until convergence.
B) The pose prior can currently only contain position information. You also have to define the coordinate system convention for each pose prior.
C) The results will be stored directly in the reconstruction.

@shuta-ochiai
Copy link

@ferreram
Thanks for your great code!
I tried the pose_prior_mapper cmd, but I got an error saying No pose priors in database...

I performed the following processes:

  1. get images and poses from ARKit app (without points clouds)
  2. convert ARKit fmt to colmap fmt (images.bin/txt, cameras.bin/txt, points3D.bin/txt(empty), database.db)
directory configuration:
arkit_data_path/
      |--- input/
            |--- frame_00001.jpg
            |--- frame_....jpg
      |--- sparse/
            |--- 0/
               |--- images.bin/txt
               |--- cameras.bin/txt
               |--- points3D.bin/txt
               |--- database.db
  1. extract feature
colmap feature_extractor 
--database_path arkit_data_path/sparse/0/database.db 
--image_path arkit_data_path/input 
--SiftExtraction.use_gpu 1 
--ImageReader.single_camera 1
  1. feature matching
colmap sequential_mathcer
--database_path arkit_data_path/sparse/0/databse.db
--SiftExtraction.use_gpu 1
  1. pose prior mapper
colmap pose_prior_mapper
--image_path arkit_data_path/input
--database_path arkit_data_path/sparse/0/database.db
--output_path sfm_processed_data_path
--Mapper.multiple_models 0
--Mapper.ba_refine_focal_length 0
--Mapper.ba_refine_extra_params 0
--overwrite_priors_covariance 1
--prior_position_std_x 0.05
--prior_position_std_y 0.05
--prior_position_std_z 0.01
  1. bundle adjuster
colmap bundle_adjuster
--input_path sfm_processed_data_path
--output_path sfm_processed_data_path
--BundleAdjustment.refine_focal_length 0
--BundleAdjustment.refine_principal_point 0
--BundleAdjustment.refine_extra_params 0

Error Encountered:

I1202 01:23:10.560431   948 sfm.cc:54] Setting up database pose priors with the same covariance matrix:                                    
0.0025      0      0                                                                                                                       
     0 0.0025      0                                                                                                                       
     0      0 0.0001                                                                                                                       
I1202 01:23:10.574162   948 incremental_pipeline.cc:237] Loading database                                                                  
I1202 01:23:10.624039   948 database_cache.cc:66] Loading cameras...                                                                       
I1202 01:23:10.628621   948 database_cache.cc:76]  1 in 0.005s                                                                             
I1202 01:23:10.628628   948 database_cache.cc:84] Loading matches...                                                                       
I1202 01:23:11.159878   948 database_cache.cc:89]  1082 in 0.531s                                                                          
I1202 01:23:11.159904   948 database_cache.cc:105] Loading images...                                                                       
I1202 01:23:16.291671   948 database_cache.cc:153]  200 in 5.132s (connected 200)                                                          
I1202 01:23:16.291709   948 database_cache.cc:164] Loading pose priors...                                                                  
I1202 01:23:16.612479   948 database_cache.cc:175]  0 in 0.321s                                                                            
I1202 01:23:16.612496   948 database_cache.cc:184] Building correspondence graph...                                                        
I1202 01:23:16.776397   948 database_cache.cc:210]  in 0.164s (ignored 0)                                                                  
I1202 01:23:16.776595   948 timer.cc:91] Elapsed time: 0.103                                                                               
I1202 01:23:16.776602   948 database_cache.cc:228] Setting up prior positions...                                                           
E1202 01:23:16.776602   948 database_cache.cc:234] No pose priors in database...                                                           
E1202 01:23:16.950085   948 sfm.cc:465] failed to create sparse model     

If you have any solutions., please let me know!

@HernandoR
Copy link
Contributor
HernandoR commented Dec 2, 2024 via email

@mattiasmar
Copy link
mattiasmar commented Dec 2, 2024

@ahojnnes I tried a basic call to create_pose_prior_bundle_adjuster, but get an exception:

    rec = pycolmap.Reconstruction('output/sfm')  #Folder containing images.bin, cameras.bin and points3D.bin
    pose_prior_bundle_adjuster = pycolmap.create_pose_prior_bundle_adjuster(
        pose_priors=pose_priors,
        reconstruction= rec
    )

pose_priors is a dict of int (image id) VS pycolmap.PosePrior objects

create_pose_prior_bundle_adjuster(): incompatible function arguments. The following argument types are supported:
    1. (options: pycolmap._core.BundleAdjustmentOptions, prior_options: pycolmap._core.PosePriorBundleAdjustmentOptions, config: pycolmap._core.BundleAdjustmentConfig, pose_priors: dict[int, pycolmap._core.PosePrior], reconstruction: pycolmap._core.Reconstruction) -> pycolmap._core.BundleAdjuster

Invoked with: kwargs: options=BundleAdjustmentOptions(loss_function_type=LossFunctionType.TRIVIAL, loss_function_scale=1.0, refine_focal_length=False, refine_principal_point=False, refine_extra_params=False, refine_extrinsics=True, print_summary=True, use_gpu=True, gpu_index='-1', min_num_residuals_for_cpu_multi_threading=50000, min_num_images_gpu_solver=50, max_num_images_direct_dense_cpu_solver=50, max_num_images_direct_sparse_cpu_solver=1000, max_num_images_direct_dense_gpu_solver=200, max_num_images_direct_sparse_gpu_solver=4000), pose_priors={1: PosePrior(position=[43.502, -30.3787, -114.512], position_covariance=[1, 0, 0, 0, 1, 0, 0, 0, 1], coordinate_system=CARTESIAN), 2: PosePrior(position=[43.4313, -30.4905, -114.934], position_covariance=[1, 0, 0, 0, 1, 0, 0, 0, 1], coordinate_system=CARTESIAN), 3: PosePrior(position=[43.5459, -30.594, -115.323], position_covariance=[1, 0, 0, 0, 1, 0, 0, 0, 1], ....

Could you share a mini example that could serve me and the community as a guide?

Version details:

COLMAP_build: str = "Commit e778be63 on 2024-11-29 with CUDA"
COLMAP_version: str = "COLMAP 3.12.0.dev0"
__ceres_version__: str = "2.3.0"
__version__: str = "3.12.0"

@ferreram ferreram deleted the loc-prior-ba branch December 2, 2024 15:13
@bbzh
Copy link
bbzh commented Dec 2, 2024

Is there an official instruction or example to use the GPS prior? That will be very useful for the community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants
0