-
Notifications
You must be signed in to change notification settings - Fork 49
[WIP] Bring some more methods from upstream and other minor fixes. #86
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
base: main
Are you sure you want to change the base?
Changes from all commits
225ca50
d234674
8cad2d9
03d9748
b69e7bb
fc930ec
55b567a
0325cd7
92bdaab
8efac4f
938a556
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| import logging | ||
| from pathlib import Path | ||
| from copy import deepcopy | ||
| from threading import Lock | ||
| import numpy as np | ||
|
|
||
| import pycolmap | ||
|
|
@@ -94,6 +95,19 @@ def __init__(self, config, outputs, capture, session_id, | |
| self.name2key[image.name]: image.image_id | ||
| for image in self.reconstruction.images.values() | ||
| } | ||
| # We cache the 3D points for mapping images to avoid parsing them from | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually in #62 (review pending) I already had 100x speedup in pose estimation by only caching the image-to-point3D ID mapping, would this be sufficient? fetching the xyz seems already pretty fast and caching it is more expensive memory-wise. The locking adds quite a lot of complexity, no?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll take a look there - maybe that's sufficient since I agree the locks complicate things. To be honest, the fastest I managed to get our pose estimation was with single-threaded + caching. I didn't investigate too much where it's coming from though. |
||
| # the reconstruction each time. If we count 5K keypoints per image, this | ||
| # leads to ~160KB / image, so even for 25K mapping images, this would | ||
| # only be ~4GB of RAM. For very large datasets, we might want to look | ||
| # into a LRU cache. | ||
| self.points3d_cache = {} | ||
| # We use a lock per image to make sure other threads using different | ||
| # images can run in parallel. These locks block for the expensive | ||
| # reconstruction parsing. | ||
| self.image_locks = {} | ||
| # We use a lock for the image locks to make sure that we do not | ||
| # create multiple locks for the same image. | ||
| self.lock = Lock() | ||
|
|
||
| def run(self, capture): | ||
| run_capture_to_empty_colmap.run(capture, [self.session_id], self.paths.sfm_empty) | ||
|
|
@@ -106,20 +120,38 @@ def run(self, capture): | |
| self.matching.paths.matches, | ||
| ) | ||
|
|
||
| def get_points3D(self, key, point2D_indices): | ||
| image = self.reconstruction.images[self.key2imageid[key]] | ||
| valid = [] | ||
| xyz = [] | ||
| ids = [] | ||
| if len(image.points2D) > 0: | ||
| for idx in point2D_indices: | ||
| p = image.points2D[idx] | ||
| valid.append(p.has_point3D()) | ||
| if valid[-1]: | ||
| ids.append(p.point3D_id) | ||
| xyz.append(self.reconstruction.points3D[ids[-1]].xyz) | ||
| return np.array(valid, bool), xyz, ids | ||
| def _get_points3D_from_cache(self, key, point2D_indices): | ||
| ids, xyz = self.points3d_cache[key] | ||
| if len(ids) == 0: | ||
| # Not registered. | ||
| return np.array([], bool), [], [] | ||
| valid = ids[point2D_indices] != -1 | ||
| return valid, xyz[point2D_indices][valid], ids[point2D_indices][valid] | ||
|
|
||
|
|
||
| def get_points3D(self, key, point2D_indices): | ||
| if key not in self.image_locks: | ||
| with self.lock: | ||
| # Key might have been added while we were waiting for the lock. | ||
| if key not in self.image_locks: | ||
| self.image_locks[key] = Lock() | ||
| if key not in self.points3d_cache: | ||
| with self.image_locks[key]: | ||
| # Key might have been added while we were waiting for the lock. | ||
| if key not in self.points3d_cache: | ||
| image = self.reconstruction.images[self.key2imageid[key]] | ||
| ids = [] | ||
| xyz = [] | ||
| for p2d in image.points2D: | ||
| if p2d.has_point3D(): | ||
| ids.append(p2d.point3D_id) | ||
| xyz.append(self.reconstruction.points3D[ids[-1]].xyz) | ||
| else: | ||
| ids.append(-1) | ||
| xyz.append([np.nan, np.nan, np.nan]) | ||
| self.points3d_cache[key] = (np.array(ids), np.array(xyz)) | ||
| return self._get_points3D_from_cache(key, point2D_indices) | ||
|
|
||
|
|
||
| class MeshLifting(Mapping): | ||
| method = { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cvg/Hierarchical-Localization@d0e8494 removes Cos/EigenPlaces but adds MegaLoc, which is much more robust (and has results on LaMAR).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the info, I'll go ahead and replace with MegaLoc and will also try that one on a currently private data split (to be released) to see where it stands (SALAD seems kinda good 😄 )