Skip to content
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

Camera pose optimization for Splatfacto #2891

Merged
merged 7 commits into from
Apr 11, 2024

Conversation

oseiskar
Copy link
Contributor

@oseiskar oseiskar commented Feb 9, 2024

Updated description, April 7: Camera pose optimization for Splatfacto, based on nerfstudio-project/gsplat#127, which is included in gsplat 0.1.9+. See #2891 (comment) for instructions and examples.

.
Original description, outdated: This PR is intended as an extension of #2885, but I could not easily create a PR to that branch, so creating a new PR instead. A detailed description in a comment in the original PR: #2885 (comment)
@jh-surh : Feel free to merge / cherry-pick any of my commits in this branch to your original PR, [...]

@ichsan2895
Copy link

Again, interesting PR. 👍
How about the result quality? Hopefully it increase the quality when using colmap.

Is it compatible with latest gsplat==0.1.5 ? or we need git install from this repo nerfstudio-project/gsplat#127 ?

@ichsan2895
Copy link

ichsan2895 commented Feb 10, 2024

Sorry, Unfortunatelly, it decrease the quality:

Playroom dataset processed by colmap 3.8: (Red line = this PR)

image
image
Camera optimization regularizer acts after 3k iters, then the PSNR begins to drop.

desolation dataset provided by ns-download-data: (Red line = this PR)

image
image

Camera optimization regularizer acts after 3k iters, then the PSNR begins to drop.

@oseiskar
Copy link
Contributor Author

oseiskar commented Feb 10, 2024

Sorry, Unfortunatelly, it decrease the quality:

This is expected. Like I commented here #2885 (comment), there are two separate cases:

  1. The current NeRF/3DGS benchmark datasets which are still images taken on a tripod. For these, COLMAP works very accurately and there's no need to further optimize the poses. If pose optimization is enabled it easily decreases quality. It might be possible to tune the hyperparameters so that this would not happen, but I have not attempted that
  2. Datasets collected with a moving mobile camera, similar to the one @jh-surh was testing with in the other PR. The goal of this PR is to improve these cases, especially in scenarios, where COLMAP has been replaced with a faster alternative like ARKit's online poses or other systems. The issue is that there is no good standard benchmark set for these at the moment (as far as I know)

I now disabled the feature by default so that the assumed target use case remains as 1. (2. can be addressed by re-enabling this on the command line as --pipeline.model.camera-optimizer.mode=SO3xR3)

Again, interesting PR. 👍 How about the result quality? Hopefully it increase the quality when using colmap.

Is it compatible with latest gsplat==0.1.5 ? or we need git install from this repo nerfstudio-project/gsplat#127 ?

No. Need to install from Git since the view matrix gradients from nerfstudio-project/gsplat#127 (or, alternatively, nerfstudio-project/gsplat#123) are neeed.

@ichsan2895
Copy link

ichsan2895 commented Feb 10, 2024

Sorry, Unfortunatelly, it decrease the quality:

This is expected. Like I commented here #2885 (comment), there are two separate cases:

1. The current NeRF/3DGS benchmark datasets which are still images taken on a tripod. For these COLMAP works very accurately and there's no need to further optimize the poses. If pose optimization is enabled it easily decreases quality. It might be possible to tune the hyperparameters so that this would not happen, but I have not attempted that

2. Datasets collected with a moving mobile camera, similar to the one @jh-surh was testing with in the [other PR](https://github.com/nerfstudio-project/nerfstudio/pull/2885). The goal of this PR is to improve these cases, especially in scenarios, where COLMAP has been replaced with a faster alternative like ARKit's online poses or other systems. The issue is that there is no good standard benchmark set for these at the moment (as far as I know)

I now disabled the feature by default so that the assumed target use case remains as 1. (2. can be addressed by re-enabling this on the command line as --pipeline.model.camera-optimizer.mode=SO3xR3)

Again, interesting PR. 👍 How about the result quality? Hopefully it increase the quality when using colmap.
Is it compatible with latest gsplat==0.1.5 ? or we need git install from this repo nerfstudio-project/gsplat#127 ?

No. Need to install from Git since the view matrix gradients from nerfstudio-project/gsplat#127 (or, alternatively, nerfstudio-project/gsplat#123) are neeed.

Thanks for your clarification, in my experiment before, I already use gsplat from this source:

git clone --branch approximate-viewmat-gradient https://github.com/SpectacularAI/gsplat
git submodule update --init --recursive

I think it is good if the camera opt can detect automatically if the poses already accurate or not. If it already accurate and it hurts quality, it will be turn off.

But I am sorry I can not coding since it too advance for me.

@kerrj
Copy link
Collaborator

kerrj commented Feb 12, 2024

I think these changes look reasonable to me, delaying pose optimization until partial convergence makes sense. @jh-surh have you had a chance to take a look?

@jb-ye
Copy link
Collaborator

jb-ye commented Feb 13, 2024

Regarding quantitative validation of this PR, Here is my suggestion:

(1) take a dataset which you think is suitable for pose optimization
(2) run a baseline with pose optimization disabled and obtain PSNR metrics on validation images.
(3a) run with pose optimization enabled for all frames (basically all images are used for training) and extract the optimized poses
(3b) use the optimized poses to re-run the same setting as done in (2) and compare the PSNR metrics on validation images.

If (3b) is better than (2), one has strong evidence that pose optimization works.

What do you think? @oseiskar

@jb-ye
Copy link
Collaborator

jb-ye commented Feb 13, 2024

I think these changes look reasonable to me, delaying pose optimization until partial convergence makes sense. @jh-surh have you had a chance to take a look?

Delay pose optimization until partial convergence might be useful for fixing a few bad local poses, but would not correct systematic drift in SfM/SLAM.

@oseiskar
Copy link
Contributor Author

Regarding quantitative validation of this PR, Here is my suggestion:

(1) take a dataset which you think is suitable for pose optimization (2) run a baseline with pose optimization disabled and obtain PSNR metrics on validation images. (3a) run with pose optimization enabled for all frames (basically all images are used for training) and extract the optimized poses (3b) use the optimized poses to re-run the same setting as done in (2) and compare the PSNR metrics on validation images.

If (3b) is better than (2), one has strong evidence that pose optimization works.

What do you think? @oseiskar

I think this makes a lot of sense. I am planning to do that in the near-ish future.

To clarify, this PR is not yet in the state where it would be robust enough for general use. The main intention was to help #2885 so that it's not necessary to reinvent the wheel in all aspects there. In particular, I think if this commit 5fe47c9 is probably a pre-requisite for getting anything working well. These new metrics 3b02a7f can also be helpful for debugging/monitoring pose optimization.

@jh-surh
Copy link
Contributor

jh-surh commented Feb 14, 2024

I think these changes look reasonable to me, delaying pose optimization until partial convergence makes sense. @jh-surh have you had a chance to take a look?

I think the changes look good. I'll try them out.

Regarding quantitative validation of this PR, Here is my suggestion:

(1) take a dataset which you think is suitable for pose optimization (2) run a baseline with pose optimization disabled and obtain PSNR metrics on validation images. (3a) run with pose optimization enabled for all frames (basically all images are used for training) and extract the optimized poses (3b) use the optimized poses to re-run the same setting as done in (2) and compare the PSNR metrics on validation images.

If (3b) is better than (2), one has strong evidence that pose optimization works.

What do you think? @oseiskar

Wouldn't (3a) showing a better PSNR already show that the pose optimization works?

@jb-ye
Copy link
Collaborator

jb-ye commented Feb 14, 2024

Wouldn't (3a) showing a better PSNR already show that the pose optimization works?

(3a) uses all images to train, so the metrics calculated on the set of validation images is biased. Evaluation on hold out set of images for calculating metrics like (3b) is unbiased and produce apple-to-apple comparison to (2).

In (3b), image data of validation sets are only used to optimize their poses, but not gaussian splat models.

@MartinEthier
Copy link

Regarding quantitative validation of this PR, Here is my suggestion:

(1) take a dataset which you think is suitable for pose optimization (2) run a baseline with pose optimization disabled and obtain PSNR metrics on validation images. (3a) run with pose optimization enabled for all frames (basically all images are used for training) and extract the optimized poses (3b) use the optimized poses to re-run the same setting as done in (2) and compare the PSNR metrics on validation images.

If (3b) is better than (2), one has strong evidence that pose optimization works.

What do you think? @oseiskar

I've been looking into ways to enable evaluation using pose optimization and I tried the method you outlined using nerfacto and nerfacto-big. For some reason, my results on the extracted optimized poses are worse than simply not using pose optimization, even though the training PSNR increases when I enable pose optimization, indicating that it helps. See my comment here for more details: #2863 (comment). Do you have any ideas why this might be the case?

@oseiskar
Copy link
Contributor Author

oseiskar commented Apr 6, 2024

@ichsan2895 @jb-ye I now rebased this on top of the current main branch (with #3019), removed deprecated workarounds and changed the hyperparameters to what we used in Gaussian Splatting on the Move.

Here's how to test branch and verify that it works: First, install and download a suitable test dataset (our version of Deblur-NeRF, which contains a variant with artificial pose noise):

conda activate nerfstudio

# download a suitable dataset
git clone https://github.com/SpectacularAI/3dgs-deblur
cd 3dgs-deblur
python download_data.py --dataset synthetic
cd ..

# check out and install this branch
https://github.com/SpectacularAI/nerfstudio
cd nerfstudio
git checkout camera-pose-optimization
pip install -e .

Then, run a basline test with the noisy pose data but without pose optimization:

ns-train splatfacto --data ../3dgs-deblur/data/inputs-processed/synthetic-posenoise/cozyroom

Then check Viser: Looks terrible (Figure 1). Now, let's run another test with pose optimization:

ns-train splatfacto --data ../3dgs-deblur/data/inputs-processed/synthetic-posenoise/cozyroom \
    --pipeline.model.camera-optimizer.mode=SO3xR3

Check viser again: Looks great (Figure 2). (Bonus: also add --pipeline.model.rasterize-mode=antialiased for best results)

Now, the caveats:

  1. Evaluating this numerically is not trivial, for the following reasons:
    a) We would also need to optimize the evaluation image poses or most of the error in, e.g., PSNR is caused by just "misaligned" evaluation images. This topic is also discussed by @LingzheZhao here.
    b) Even if we do, cases with very well-optimized poses probably degrade (this concrens of most academic benchmark data out there, which is mostly consists of still images taken on tripods, or synthetics). This is because we waste some iterations that could be spent refining the 3D model into refining the poses, especially early in the optimization and during this time, when camera poses can move a lot, the 3D model remains blurrier than without pose opt. This can be solved with a 2-pass approach, which we also used in the paper.
    c) If evaluation images are used during training, even in the first pass, one could argue that they improve the model and the results are overly optimistic. To avoid this, the two-pass optimization should actually work like this: 1st pass: train normally without evaluation images, 2nd pass: optimize evaluation image poses with fixed Gaussian parameters. I have not tried to implement this since I think it's really a bit overkill in this context.

  2. The pose optimization can fail depending on the scene. This is sensitive to the following parameters: pipeline.model.camera-optimizer.trans-l2-penalty and auto-scale-poses (dataparser), which is relevant if the dataset has absolute metric scale (e.g., from VISLAM). It should be possible to improve this in the future with more carefully designed priors, e.g., penalizing maxium deviation from the initial poses more strongly.

In any case, I think this PR is now in a mergeable state despite the (minor) weaknesses above. The pose optimization is now anyway off by default.

Figure 1: Baseline

image

Figure 2: With pose optimization

image

This was actually with --pipeline.model.rasterize-mode=antialiased. Here's how it looks with the default rasterization. Still better than with noisy poses, but the new rasterization gives a nice super-resolution capability here (training data is 600x400)

@oseiskar oseiskar force-pushed the camera-pose-optimization branch 2 times, most recently from 730557a to 4f43b8e Compare April 6, 2024 10:08
@oseiskar oseiskar changed the title Camera pose optimization tweaks for Splatfacto Camera pose optimization for Splatfacto Apr 7, 2024
@jb-ye
Copy link
Collaborator

jb-ye commented Apr 8, 2024

@oseiskar Thanks, I will try to take a closer look in the next few days.

Copy link
Collaborator

@jb-ye jb-ye left a comment

Choose a reason for hiding this comment

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

Looks good to me, some minor comments.

@@ -632,8 +632,10 @@
},
"quats": {"optimizer": AdamOptimizerConfig(lr=0.001, eps=1e-15), "scheduler": None},
"camera_opt": {
"optimizer": AdamOptimizerConfig(lr=1e-3, eps=1e-15),
"scheduler": ExponentialDecaySchedulerConfig(lr_final=5e-5, max_steps=30000),
"optimizer": AdamOptimizerConfig(lr=1e-4, eps=1e-15),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could you add this change to "splatfacto-big" config?

@ichsan2895
Copy link

Hello, interesting PR to be implemented.

Here is my own dataset (already processed with colmap) with some of motion blur. Already processed by colmap & colmap image_undistorter Feel free for testing it.

Lubuk_torok_scenery

@oseiskar
Copy link
Contributor Author

@jb-ye : Done. I tested very briefly (i.e., only with this same synthetic scene) that it looks reasonable and better than the old splatfacto-big camera pose opt. defaults. This was the case (result here) so these are probably a good starting point for further hyperparameter tuning.

@ichsan2895 To clarify, this PR does not implement motion blur compensation. This is just one of the building blocks that can help in that goal and other tasks as well. For testing the Gaussian Splatting on the Move method with custom data, see here.

@lxzbg
Copy link

lxzbg commented Apr 11, 2024

@oseiskar Great work. I used ARkit's pose based data for testing, and it did work.
However, I have some observations.

  1. When the pose error is small, it can be corrected very well;
  2. When the pose error is large, it cannot be completely corrected (I tried adjusting the number of iterations, learning rate, and warnup, but this only had a little effect);
  3. The pose optimization is more accurate in the inner area of the surround shot, but in the surrounding area, it seems that pose optimization is not that effective (maybe this observation is incorrect).

Is there anything that can be improved here?

@oseiskar
Copy link
Contributor Author

@lxzbg Thank you for testing, good to hear that this also gave positive results in your test. I think those observations all make sense. In general, there is a lot that can be improved around this topic, but probably not in the scope of this PR.

Getting 3DGS to work robustly for data with larger pose errors probably requires a combination of different techniques, where 3DGS pose optimization like this is one piece in the puzzle. Replacing COLMAP with some of the new methods like Dust3r or Cameras as Rays seems like a promising direction. This was already verified to work well by the InstantSplat authors.

It is probably also possible to improve performance a bit by further tuning of these hyperparameters, but I would not expect miracles there. I am not planning to try further performance improvements in this PR.

Copy link
Collaborator

@jb-ye jb-ye left a comment

Choose a reason for hiding this comment

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

thanks for the effort!

@jb-ye jb-ye enabled auto-merge (squash) April 11, 2024 17:13
@jb-ye
Copy link
Collaborator

jb-ye commented Apr 11, 2024

@oseiskar You need to rebase and the PR should be auto-merged.

auto-merge was automatically disabled April 11, 2024 18:06

Head branch was pushed to by a user without write access

@oseiskar
Copy link
Contributor Author

@jb-ye Great! I now rebased but auto-merge seems to have been auto-disabled

@jb-ye jb-ye merged commit eba72db into nerfstudio-project:main Apr 11, 2024
2 checks passed
Masks-code added a commit to Masks-code/nerfstudio that referenced this pull request Apr 23, 2024
commit d9b022b
Author: J.Y <132313008+jb-ye@users.noreply.github.com>
Date:   Fri Apr 19 14:03:55 2024 -0400

    Allow alpha transparency training for blender datasets input (nerfstudio-project#3088)

    Allow alpha transparency training for rgba input

    Co-authored-by: Justin Kerr <justin.g.kerr@gmail.com>

commit eddf2d2
Author: Congrong Xu <50019703+KevinXu02@users.noreply.github.com>
Date:   Thu Apr 18 17:37:50 2024 -0700

    Changes for trainer.py to support the Gradio webui (nerfstudio-project#3046)

    * changes for trainer to support webui

    * Update trainer to support webui

    * format

    * add a seperated shutdown() function to stop training

    * typo fix

    * get rid of _stop_viewer_server()

    * Update trainer.py

    * organize import

    ---------

    Co-authored-by: Brent Yi <yibrenth@gmail.com>

commit 45d8bb7
Author: Justin Kerr <justin.g.kerr@gmail.com>
Date:   Wed Apr 17 23:54:43 2024 -0700

    updates to apply_pca_colormap (nerfstudio-project#3086)

    * improvements to pca_colormap: allow input pca matrix, optional ignore_zeros arg

    * typo

commit babf577
Author: Patrick Morgan <patrick@patrick-morgan.net>
Date:   Fri Apr 12 14:23:47 2024 -0700

    Fix call to detect ODM reconstruction file (nerfstudio-project#3018)

commit a64026f
Author: Justin Kerr <justin.g.kerr@gmail.com>
Date:   Fri Apr 12 12:32:22 2024 -0700

    shift principle points by .5 in undistortion (nerfstudio-project#3071)

    * shift principle points by .5

    * fix ordering

    * add fisheye offset

commit c302cc5
Author: Gunjan Chhablani <chhablani.gunjan@gmail.com>
Date:   Thu Apr 11 16:41:14 2024 -0400

    Add pointcloud loading for blender parser (nerfstudio-project#2902)

    * Add pointcloud loading for blender parser

    * Fix argument

    * Fix docstring

    * Fix metadata in dataparsers

    * Add changes from review

    * Avoid changing default behavior

    * Apply `scale_factor` to loaded points

    ---------

    Co-authored-by: Brent Yi <yibrenth@gmail.com>

commit 03bdeff
Author: hyperzy <50564821+hyperzy@users.noreply.github.com>
Date:   Thu Apr 11 14:56:37 2024 -0400

    Fixed Unexpectedly huge RAM consumption of parallel datamanager (nerfstudio-project#3060)

    * Reduced the memory usage by caching image after the datamanager process starts

commit 4714ae7
Author: J.Y <132313008+jb-ye@users.noreply.github.com>
Date:   Thu Apr 11 14:37:02 2024 -0400

    write eval combined images for diagnostics (nerfstudio-project#3070)

commit eba72db
Author: Otto Seiskari <otto.seiskari@gmail.com>
Date:   Thu Apr 11 21:23:17 2024 +0300

    Camera pose optimization for Splatfacto (nerfstudio-project#2891)

    * Add pose optimization to Splatfacto

    * Disable Splatfacto pose optimization by default

    * Improve apply_to_camera for Gaussian Splatting pose optimization

    Do not chain modifications to camera_to_worlds to improve
    numerical stability and enable L2 rot/trans penalties.

    * Add separate mean and max rot/trans metrics to camera-opt

    * Tweak pose optimization hyperparameters

    Parameters used in the Gaussian Splatting on the Move paper v1

    * Unit test fix for new cameara_optimizer training metrics

    * Adjust splatfacto-big camera pose optimization parameters

    Same parameters as in normal Splatfacto

    ---------

    Co-authored-by: jh-surh <jh.surh@bucketplace.net>

commit 2d9bbe5
Author: dberga <dberga@users.noreply.github.com>
Date:   Thu Apr 11 04:04:33 2024 +0200

    fix exporter.py for FullImageDataManager and RandomCamerasDataManager (nerfstudio-project#3065)

    * fix exporter.py for FullImageDataManager and RandomCamerasDataManager

    * sort imports

    * ruff

    ---------

    Co-authored-by: Brent Yi <yibrenth@gmail.com>

commit c381fc8
Author: Justin Kerr <justin.g.kerr@gmail.com>
Date:   Wed Apr 10 18:59:20 2024 -0700

    Fix custom elements nested under @Property (nerfstudio-project#3066)

    * patch custom elements bug

    * Skip `cached_property`

    * fomrat

    * comment, type hint

    ---------

    Co-authored-by: Brent Yi <yibrenth@gmail.com>

commit d1fc2ee
Author: Saurav Maheshkar <sauravvmaheshkar@gmail.com>
Date:   Mon Apr 8 23:46:00 2024 +0100

    feat(ci): migrate to `uv` in CI (nerfstudio-project#3038)

    * feat(ci): migrate to `uv` in CI

    * feat(ci): drop upgrade strategy

    * feat(ci): use `uv` in docs workflow

    * fix(ci/doc): update sphinx build cmd

    * fix(ci/doc): specify python path

    * (experimental) simplify

    * remove venv

    * Revert line wrap change for doc.yml

    ---------

    Co-authored-by: Brent Yi <yibrenth@gmail.com>

commit 2b91715
Author: Sahil Jain <sahilja2@andrew.cmu.edu>
Date:   Mon Apr 8 13:04:20 2024 -0400

    Fix config loading for Eyeful Tower dataset (nerfstudio-project#3054)

    Add test_filenames to transforms.json generated by eyeful_tower.py

commit 26804f8
Author: Ling Jing <111032642+Jing1Ling@users.noreply.github.com>
Date:   Tue Apr 9 00:07:21 2024 +0800

    Make colmapDataParser compatible with 360_v2 dataset format (nerfstudio-project#2860)

    * added an option to colmapdataparser to round up the image size when downscaling

    * add round mode and update ffmpeg command

    * [fix] wrong variable order

    * update format

    ---------

    Co-authored-by: Jing <jing1ling@intel.com>

commit 911091c
Author: Jan-Niklas Dihlmann <j.dihlmann@googlemail.com>
Date:   Mon Apr 8 16:17:56 2024 +0200

    Added SIGNeRF to Nerfstudio methods  (nerfstudio-project#3053)

    * feat: signerf as nerfstudio method

    * fix: formating issues and indexing
Michael-Spleenlab pushed a commit to Michael-Spleenlab/nerfstudio that referenced this pull request Apr 26, 2024
* Add pose optimization to Splatfacto

* Disable Splatfacto pose optimization by default

* Improve apply_to_camera for Gaussian Splatting pose optimization

Do not chain modifications to camera_to_worlds to improve
numerical stability and enable L2 rot/trans penalties.

* Add separate mean and max rot/trans metrics to camera-opt

* Tweak pose optimization hyperparameters

Parameters used in the Gaussian Splatting on the Move paper v1

* Unit test fix for new cameara_optimizer training metrics

* Adjust splatfacto-big camera pose optimization parameters

Same parameters as in normal Splatfacto

---------

Co-authored-by: jh-surh <jh.surh@bucketplace.net>
@oseiskar oseiskar deleted the camera-pose-optimization branch May 30, 2024 19:53
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.

None yet

7 participants