51 def __init__(self, num_points: int, reprojection_threshold: float, min_dist_new_point: float, max_depth_error_visible: float):
55 num_points (int): Maximum number of points that can be stored in the map.
56 reprojection_threshold (float): Reprojection threshold (in pixels) that is used to filter outliers.
57 When map points are matched with points in an image,
58 if their reprojection is too far from the actually observed point, then they are marked as outliers and removed.
59 min_dist_new_point (float): Minimum distance (in meters) that a point should have to all the map points to be considered as a candidate for addition to the map
60 max_depth_error_visible (float): Maximum depth (in meters) error that is tolerated for a point to be considered as visible. Used to filter out self occlusion.
107 def update(self, frame: RBFeatureTrackerInput, cMo: HomogeneousMatrix, render_depth: ImageFloat, depth_map: ImageFloat, idx_curr_matched: np.ndarray, idx_matched_map: np.ndarray, current_kps: np.ndarray, current_descriptors: torch.Tensor) -> List[int]:
108 """ Update the map: Remove outliers and add new points
111 frame (RBFeatureTrackerInput): Input frame
112 cMo (HomogeneousMatrix): Current pose corresponding to the acquired frame
113 render_depth (ImageFloat): Depth in render
114 depth_map (ImageFloat): Depth observed by the camera (can be zero sized image, in which case it isn't used)
115 idx_curr_matched (np.ndarray): Indices of the points points that were matched for the set of current keypoints (in the camera frame).
116 idx_matched_map (np.ndarray): Indices of the points that were matched for the set of points from this map. After this method has been called it may no longer be valid.
117 current_kps (np.ndarray): N x 2 array that contains the pixel locations of all the keypoints detected in the image. Will be indexed with idx_curr_matched
118 current_descriptors (torch.Tensor): N x D tensor containing the descriptors associated to the keypoints observed in the image.
121 List[int]: The indices of the points that were removed
123 if current_descriptors
is None or current_kps
is None:
126 if idx_curr_matched
is not None:
127 assert len(idx_curr_matched.shape) == 1
128 assert len(idx_matched_map.shape) == 1
129 assert len(idx_curr_matched) == len(idx_matched_map)
131 indices_outliers = []
132 if self.
has_points()
and idx_curr_matched
is not None and idx_matched_map
is not None:
135 if len(idx_matched_map) > 0:
136 idx_map = ArrayInt2D.view(idx_matched_map[:,
None].astype(np.int32))
137 cX, x, uvs = Matrix(), Matrix(), Matrix()
138 self.
point_map.project(cam, idx_map, cMo, cX, x, uvs)
139 indices_outliers = self.
point_map.getOutliers(idx_map, uvs, Matrix.view(np.ascontiguousarray(current_kps[idx_curr_matched])))
140 self.
descriptors[idx_matched_map] = current_descriptors[idx_curr_matched]
145 num_points = len(current_kps)
148 if idx_curr_matched
is None:
149 indices_points_not_matched_object = np.arange(num_points, dtype=np.int32)
151 indices_points_not_matched_object = np.ascontiguousarray(np.setdiff1d(np.arange(num_points, dtype=np.int32), idx_curr_matched, assume_unique=
True))
152 points_to_add_px = np.ascontiguousarray(current_kps[indices_points_not_matched_object], dtype=np.float64)
153 if len(indices_points_not_matched_object) == 0:
154 indices_array = ArrayInt2D()
156 indices_array = ArrayInt2D.view(indices_points_not_matched_object[...,
None])
162 render_normals = frame.renders.normals
if render_depth
is not None else ImageRGBf()
163 if render_depth
is None:
164 render_depth = ImageFloat()
166 indices_not_matched_to_add = self.
point_map.selectValidNewCandidates(cam, cMo, indices_array, Matrix.view(points_to_add_px), render_depth, depth_map, render_normals, oX_new, oN_new)
168 self.
set_points_to_add(oX_new, current_descriptors[indices_not_matched_to_add], oN_new)
171 return indices_to_remove
184 """Actually remove outliers and add new points to the map.
185 This step needs to be done in one go so as to not invalidate any indexing that was done prior to this.
188 List[int]: The indices of the points that were removed
192 outlier_array = ArrayInt2D()
194 outlier_array = ArrayInt2D.view(np.ascontiguousarray(self.
indices_removal)[:,
None].astype(np.int32))
197 if len(removed_indices) > 0:
201 kept_indices = np.setdiff1d(np.arange(len(self.
descriptors)), np.ascontiguousarray(removed_indices), assume_unique=
True)
202 kept_indices = torch.tensor(kept_indices, device=self.
descriptors.device)
214 return removed_indices
216 def get_px_proj(self, indices: np.ndarray, cam: CameraParameters, cMo: HomogeneousMatrix) -> Matrix:
217 """Helper function to compute the pixel coordinates of a set of map points.
220 indices (np.ndarray): The indices of the points for which to compute the projection
221 cam (CameraParameters): Camera intrinsics
222 cMo (HomogeneousMatrix): Camera to map reference pose
225 Matrix: a indices.shape[0] x 2 Matrix containing the pixel coordinates of the 3D points in the camera frame
227 indices = ArrayInt2D()
if len(indices) == 0
else ArrayInt2D(indices[...,
None].astype(np.int32))
228 cX, xs, uvs = Matrix(), Matrix(), Matrix()
229 self.
point_map.project(cam, indices, cMo, cX, xs, uvs)