22 py::module m_nns = m.def_submodule(
"nns");
23 py::class_<NearestNeighborSearch, std::shared_ptr<NearestNeighborSearch>>
24 nns(m_nns,
"NearestNeighborSearch",
25 R
"(NearestNeighborSearch class for nearest neighbor search.
27 This class holds multiple index types to accelerate various nearest neighbor
28 search operations for a dataset of points with shape {n,d} with `n` as the number
29 of points and `d` as the dimension of the points. The class supports knn search,
30 fixed-radius search, multi-radius search, and hybrid search.
33 The following example demonstrates how to perform knn search using the class::
35 import cloudViewer as cv3d
38 dataset = np.random.rand(10,3)
39 query_points = np.random.rand(5,3)
41 nns = cv3d.core.nns.NearestNeighborSearch(dataset)
43 # initialize the knn_index before we can use knn_search
46 # perform knn search to get the 3 closest points with respect to the
47 # Euclidean distance. The returned distance is given as the squared
49 indices, squared_distances = nns.knn_search(query_points, knn=3)
54 nns.def(py::init<const Tensor &, const Dtype>(),
"dataset_points"_a,
59 R
"(Initialize the index for knn search.
61 This function needs to be called once before performing search operations.
71 return self.FixedRadiusIndex();
73 return self.FixedRadiusIndex(radius.value());
76 py::arg(
"radius") = py::none(),
77 R
"(Initialize the index for fixed-radius search.
79 This function needs to be called once before performing search operations.
82 radius (float, optional): Radius value for fixed-radius search. Required
83 for GPU fixed radius index.
90 R
"(Initialize the index for multi-radius search.
92 This function needs to be called once before performing search operations.
102 return self.HybridIndex();
104 return self.HybridIndex(radius.
value());
107 py::arg(
"radius") = py::none(),
108 R
"(Initialize the index for hybrid search.
110 This function needs to be called once before performing search operations.
113 radius (float, optional): Radius value for hybrid search. Required
114 for GPU hybrid index.
123 R
"(Perform knn search.
126 To use knn_search initialize the index using knn_index before calling this function.
129 query_points (cloudViewer.core.Tensor): Query points with shape {n, d}.
130 knn (int): Number of neighbors to search per query point.
133 The following searches the 3 nearest neighbors for random dataset and query points::
135 import cloudViewer as cv3d
138 dataset = np.random.rand(10,3)
139 query_points = np.random.rand(5,3)
141 nns = cv3d.core.nns.NearestNeighborSearch(dataset)
143 # initialize the knn_index before we can use knn_search
146 # perform knn search to get the 3 closest points with respect to the
147 # Euclidean distance. The returned distance is given as the squared
149 indices, squared_distances = nns.knn_search(query_points, knn=3)
152 Tuple of Tensors (indices, squared_distances).
153 - indices: Tensor of shape {n, knn}.
154 - squared_distances: Tensor of shape {n, knn}. The distances are squared L2 distances.
159 "fixed_radius_search",
163 return self.FixedRadiusSearch(query_points, radius,
true);
165 return self.FixedRadiusSearch(query_points, radius,
169 py::arg(
"query_points"), py::arg(
"radius"),
170 py::arg(
"sort") = py::none(),
171 R
"(Perform fixed-radius search.
174 To use fixed_radius_search initialize the index using fixed_radius_index before calling this function.
177 query_points (cloudViewer.core.Tensor): Query points with shape {n, d}.
178 radius (float): Radius value for fixed-radius search. Note that this
179 parameter can differ from the radius used to initialize the index
180 for convenience, which may cause the index to be rebuilt for GPU
182 sort (bool, optional): Sort the results by distance. Default is True.
185 Tuple of Tensors (indices, splits, distances).
186 - indices: The indices of the neighbors.
187 - distances: The squared L2 distances.
188 - splits: The splits of the indices and distances defining the start
189 and exclusive end of each query point's neighbors. The shape is {num_queries+1}
192 The following searches the neighbors within a radius of 1.0 a set of data and query points::
194 # define data and query points
201 [0.3,2.4,1.4]], dtype=np.float32)
210 nns = cv3d.core.nns.NearestNeighborSearch(points)
211 nns.fixed_radius_index(radius=1.0)
213 neighbors_index, neighbors_distance, neighbors_splits = nns.fixed_radius_search(queries, radius=1.0, sort=True)
214 # returns neighbors_index = [1, 2, 5, 5]
215 # neighbors_distance = [0.03 0.75 0.56000006 0.62]
216 # neighbors_splits = [0, 2, 3, 4, 4]
218 for i, (start_i, end_i) in enumerate(zip(neighbors_splits, neighbors_splits[1:])):
219 start_i = start_i.item()
221 print(f"query_point {i} has the neighbors {neighbors_index[start_i:end_i].numpy()} "
222 f"with squared distances {neighbors_distance[start_i:end_i].numpy()}")
226 "query_points"_a,
"radii"_a,
227 R
"(Perform multi-radius search. Each query point has an independent radius.
230 To use multi_radius_search initialize the index using multi_radius_index before calling this function.
233 query_points (cloudViewer.core.Tensor): Query points with shape {n, d}.
234 radii (cloudViewer.core.Tensor): Radii of query points. Each query point has one radius.
237 Tuple of Tensors (indices, splits, distances).
238 - indices: The indices of the neighbors.
239 - distances: The squared L2 distances.
240 - splits: The splits of the indices and distances defining the start
241 and exclusive end of each query point's neighbors. The shape is {num_queries+1}
244 The following searches the neighbors with an individual radius for each query point::
246 # define data, query points and radii
253 [0.3,2.4,1.4]], dtype=np.float32)
262 radii = np.array([0.5, 1.0, 1.5, 2], dtype=np.float32)
264 nns = cv3d.core.nns.NearestNeighborSearch(points)
266 nns.multi_radius_index()
268 neighbors_index, neighbors_distance, neighbors_splits = nns.multi_radius_search(queries, radii)
269 # returns neighbors_index = [1 5 5 3 4]
270 # neighbors_distance = [0.03 0.56 0.62 1.76 1.87]
271 # neighbors_splits = [0 1 2 5 5]
274 for i, (start_i, end_i) in enumerate(zip(neighbors_splits, neighbors_splits[1:])):
275 start_i = start_i.item()
277 print(f"query_point {i} has the neighbors {neighbors_index[start_i:end_i].numpy()} "
278 f"with squared distances {neighbors_distance[start_i:end_i].numpy()}")
282 "query_points"_a,
"radius"_a,
"max_knn"_a,
283 R
"(Perform hybrid search.
285 Hybrid search behaves similarly to fixed-radius search, but with a maximum number of neighbors to search per query point.
288 To use hybrid_search initialize the index using hybrid_index before calling this function.
291 query_points (cloudViewer.core.Tensor): Query points with shape {n, d}.
292 radius (float): Radius value for hybrid search.
293 max_knn (int): Maximum number of neighbor to search per query.
296 Tuple of Tensors (indices, distances, counts)
297 - indices: The indices of the neighbors with shape {n, max_knn}.
298 If there are less than max_knn neighbors within the radius then the
299 last entries are padded with -1.
300 - distances: The squared L2 distances with shape {n, max_knn}.
301 If there are less than max_knn neighbors within the radius then the
302 last entries are padded with 0.
303 - counts: Counts of neighbour for each query points with shape {n}.
A Class for nearest neighbor search.
std::tuple< Tensor, Tensor, Tensor > HybridSearch(const Tensor &query_points, const double radius, const int max_knn) const
std::tuple< Tensor, Tensor, Tensor > MultiRadiusSearch(const Tensor &query_points, const Tensor &radii)
std::pair< Tensor, Tensor > KnnSearch(const Tensor &query_points, int knn)
constexpr bool has_value() const noexcept
constexpr T const & value() const &
void pybind_core_nns(py::module &m)
Generic file read and write utility for python interface.