colmap icon indicating copy to clipboard operation
colmap copied to clipboard

Pose Prior based Incremental Mapper

Open ferreram opened this issue 1 year ago • 2 comments

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.

ferreram avatar Jul 17 '24 15:07 ferreram

@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.

ferreram avatar Aug 20 '24 10:08 ferreram

On the high level, this looks great to me, thank you for your efforts to implement this feature and the diligence on implementing tests, etc. I left a few suggestions as comments.

ahojnnes avatar Aug 26 '24 08:08 ahojnnes

it is a fantastic feature. But i'm a little confusing now about the PosePrior class in this repo. As to my understanding, this class can only hold the Position prior that is only the Translation Vector prior known is used. and (do point out if i'm wrong) i understand your initial idea is to use the full prior pose, so where the Quaternion is hiding?

HernandoR avatar Sep 11 '24 09:09 HernandoR

@HernandoR Very good point. The PosePrior and PosePriorBA only handle position priors for now but can be extended to orientation priors in the future. We don't have good data to develop this for now - I guess that such priors are most likely to be obtained with compass?

sarlinpe avatar Sep 14 '24 17:09 sarlinpe

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

B1ueber2y avatar Sep 29 '24 12:09 B1ueber2y

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

ferreram avatar Sep 30 '24 11:09 ferreram

@ferreram Thank you!

ahojnnes avatar Sep 30 '24 14:09 ahojnnes

Is there a pycolmap interface for the pose_prior_mapper functionality?

mattiasmar avatar Nov 28 '24 14:11 mattiasmar

Yes https://github.com/colmap/colmap/blob/1a497f023153cf7f7074e692e066137342ab645e/src/pycolmap/estimators/bundle_adjustment.cc#L195-L201

sarlinpe avatar Nov 28 '24 14:11 sarlinpe

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()

mattiasmar avatar Nov 28 '24 16:11 mattiasmar

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.

ahojnnes avatar Nov 29 '24 11:11 ahojnnes

@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!

shuta-ochiai avatar Dec 02 '24 02:12 shuta-ochiai

To my knowledge, you have to insert the pose prior to the database, ie. the database.db. Colmap itself can only read and convert that info from exif info of the images. Please check if your images have corresponding information. Otherwise you have to insert manually.

I think there is a py interface named writeposeprior, please checkout on the pycolmap directory.

Liu Zhen


From: Shuta Ochiai @.> Sent: Monday, December 2, 2024 10:38:55 AM To: colmap/colmap @.> Cc: Liu Zhen @.>; Mention @.> Subject: Re: [colmap/colmap] Pose Prior based Incremental Mapper (PR #2660)

@ferreramhttps://github.com/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!

— Reply to this email directly, view it on GitHubhttps://github.com/colmap/colmap/pull/2660#issuecomment-2510443836, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AK4XSWCYXGHHHCF6BROZINT2DPB37AVCNFSM6AAAAABLA434QSVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMJQGQ2DGOBTGY. You are receiving this because you were mentioned.Message ID: @.***>

HernandoR avatar Dec 02 '24 02:12 HernandoR

@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"

mattiasmar avatar Dec 02 '24 14:12 mattiasmar

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

bbzh avatar Dec 02 '24 21:12 bbzh