8000 Customized python interface for bundle adjustment by B1ueber2y · Pull Request #2509 · colmap/colmap · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Customized python interface for bundle adjustment #2509

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 47 commits into from
May 1, 2024

Conversation

B1ueber2y
Copy link
Contributor
@B1ueber2y B1ueber2y commented Apr 11, 2024

This draft PR includes the following updates:

  1. refactorization of the BundleAdjuster with better modular design (with equivalent logic)
  2. Python pipeline (https://github.com/B1ueber2y/colmap/blob/features/custom_ba/pycolmap/custom_bundle_adjustment.py) for "adjust_local_bundle", "adjust_global_bundle", "iterative_local_refinement", "iterative_global_refinement" with equivalent logic as C++. The bundle adjustment interface in the custom_incremental_mapping is also updated into the new Python implementation
  3. (planned feature, not working yet). Exposing the ceres problem from BundleAdjuster to be extensible in Python with pyceres

This PR is marked as draft because the attempt on exposing the ceres problem is not working until now. Specifically, the commented section here (https://github.com/B1ueber2y/colmap/blob/features/custom_ba/pycolmap/custom_bundle_adjustment.py#L14-L27) raises segfault at L24, where pyceres.solve cannot work on a C++ constructed ceres problem. (I hope this is not a silly bug)

Since i m on vacation from tomorrow to Tuesday night and do not want to potentially block relevant development, I submit this PR and sincerely ask for help on this particular issue. let me cc potentially relevant experts on pybind11 and pyceres in case you have time to help :) @sarlinpe @Phil26AT @ahojnnes @Zador-Pataki

Thanks in advance!

@B1ueber2y B1ueber2y marked this pull request as draft April 11, 2024 20:03
@B1ueber2y
Copy link
Contributor Author
B1ueber2y commented Apr 11, 2024

Also to add to this, the new example python code on bundle adjustment needs pyceres as a dependency once the issue is fixed. We need to specify this somewhere.

Also, Python code needs to be formatted with black after this is fixed.

@B1ueber2y
Copy link
Contributor Author
B1ueber2y commented Apr 20, 2024

As the issue of extending C++ constructed ceres problem has not been resolved until now, I finished another alternative attempt by reimplementing a python class of bundle adjuster (PyBundleAdjuster) here: https://github.com/B1ueber2y/colmap/blob/features/custom_ba/pycolmap/custom_bundle_adjustment.py#L12

The example interface is here: https://github.com/B1ueber2y/colmap/blob/features/custom_ba/pycolmap/custom_bundle_adjustment.py#L193-L195, with C++ and Python alternatives for constructing and solving the bundle adjustment, corresponding to estimators/bundle_adjustment.h in COLMAP.

From my test, the bundle adjustment results from this is completely equivalent to the C++ counterpart, while having the ceres problem exposed with pyceres. The fact that the problem is constructed in Python leads to slower performance (12s to 25s for the example test)

With this feature, it will be pretty easy to:

  1. add losses on top of the COLMAP BA from different sparse features, sensors and geometric modeling
  2. migrate into different python-based optimization framework other than ceres (by substituting the problem construction and solving) and potentially integrating learning-based deep losses.

If agreed, we can put it into the pycolmap package, such that one can use for example pycolmap.PyBundleAdjuster for gettting the ceres problem in pyceres form from COLMAP.

Minor: The opaque binding of ListPoint2D is deprecated since #2443, leading to slow copying behavior for image.points2D. Thus, I added a "Point2D" getter and use "image.point2D(point2D_id)" for now before this is fixed.

cc: @sarlinpe @ahojnnes

@B1ueber2y B1ueber2y marked this pull request as ready for review April 20, 2024 14:57
@B1ueber2y
Copy link
Contributor Author

The issue is solved. It was due to a lifetime issue for the loss function, where there needs to be a stand-alone line in Python to hold the lifetime of the loss function: https://github.com/B1ueber2y/colmap/blob/features/custom_ba/pycolmap/custom_bundle_adjustment.py#L196.

Now the binding of bundle adjuster pycolmap.BundleAdjuster can work perfectly as here: https://github.com/B1ueber2y/colmap/blob/features/custom_ba/pycolmap/custom_bundle_adjustment.py#L193-L203, with similar performance. The Python class PyBundleAdjuster is commented as an alternative for the reference.

@B1ueber2y B1ueber2y marked this pull request as ready for review April 24, 2024 16:11
@@ -170,14 +172,22 @@ class BundleAdjuster {

bool Solve(Reconstruction* reconstruction);

// Get the Ceres solver summary for the last call to `Solve`.
// Set up the problem
void SetUpProblem(Reconstruction* reconstruction,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn m 8000 ore.

Would it make sense to pass the reconstruction to the constructor such that it doesn't need to be provided as argument most of its member functions? I can't see any use case where we need to use a different reconstruction between function calls. Maybe for future PRs @ahojnnes

@B1ueber2y
Copy link
Contributor Author
B1ueber2y commented Apr 24, 2024

However, just realizing that although the issue can be solved with the fix, with the current design one still needs to be careful that the lifetime of the loss function is held somewhere in Python, which is extremely dangerous. Let me add a loss function attribute in the COLMAP bundle adjustment options from the C++ end, to hold the life of the loss.

@B1ueber2y B1ueber2y marked this pull request as draft April 24, 2024 16:27
@B1ueber2y
Copy link
Contributor Author
B1ueber2y commented Apr 24, 2024

However, just realizing that although the issue can be solved with the fix, with the current design one still needs to be careful that the lifetime of the loss function is held somewhere in Python, which is extremely dangerous. Let me add a loss function attribute in the COLMAP bundle adjustment options from the C++ end, to hold the life of the loss.

In the end, this was done with a cleaner way by using the keep_alive feature in pybind11.

@B1ueber2y B1ueber2y marked this pull request as ready for review April 24, 2024 16:57
@@ -296,6 +296,7 @@ void BindSfM(py::module& m) {
auto PyBundleAdjustmentOptions =
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't we move the binding of BundleAdjustmentOptions to estimators/bundle_adjustment.cc since it is defined in the corresponding COLMAP file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we should. Also we should move the binding of IncrementalPipelineOptions to the corresponding file in sfm folder as well. I didnt update the structure pipeline/sfm.cc for both commits but I also believe that moving would be more reasonable.

Copy link
Member

Choose a reason for hiding this comment

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

Ok can do in the next PR then

@sarlinpe sarlinpe merged commit 6fb0283 into colmap:main May 1, 2024
@B1ueber2y B1ueber2y deleted the features/custom_ba branch May 1, 2024 20:00
@henry123-boy
Copy link

Thank you very much for making Ceres and COLMAP user - friendly with Python. I'm trying to add new residuals by defining a custom cost function in Python on top of pycolmap.create_default_bundle_adjuster, but it runs much slower than the original. Could you please give me some guidance on how to modify the relevant parts in the COLMAP C++ source code and rebuild pycolmap? Any advice would be greatly appreciated.

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.

4 participants
0