ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
feature.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
9 
12 #include "pybind/docstring.h"
14 
15 namespace cloudViewer {
16 namespace t {
17 namespace pipelines {
18 namespace registration {
19 
20 void pybind_feature(py::module &m_registration) {
21  m_registration.def("compute_fpfh_feature", &ComputeFPFHFeature,
22  py::call_guard<py::gil_scoped_release>(), "input"_a,
23  "max_nn"_a = 100, "radius"_a = py::none(),
24  "indices"_a = py::none(),
25  R"(Function to compute FPFH feature for a point cloud.
26 
27 It uses KNN search (Not recommended to use on GPU) if only max_nn parameter
28 is provided, Radius search (Not recommended to use on GPU) if only radius
29 parameter is provided, and Hybrid search (Recommended) if both are provided.
30 If indices is provided, the function will compute FPFH features only on the
31 selected points.
32 
33 Args:
34  input (cloudViewer.core.Tensor): The input point cloud with data type float32 or float64.
35  max_nn (int, optional): Neighbor search max neighbors parameter.
36  Default is 100.
37  radius (float, optional): Neighbor search radius parameter.
38  Recommended value is ~5x voxel size.
39  indices (cloudViewer.core.Tensor, optional): Tensor with the indices of the points to
40  compute FPFH features on. Default is None.
41 
42 Returns:
43  The FPFH feature tensor with shape (N, 33).
44 
45 Example:
46  This example shows how to compute the FPFH features for a point cloud::
47 
48  import cloudViewer as cv3d
49  # read and downsample point clouds
50  paths = cv3d.data.DemoICPPointClouds().paths
51  voxel_size = 0.01
52  pcd = cv3d.t.io.read_point_cloud(paths[0]).voxel_down_sample(voxel_size)
53 
54  # compute FPFH features
55  pcd_fpfh = cv3d.t.pipelines.registration.compute_fpfh_feature(pcd, radius=5*voxel_size)
56  )"
57 
58  );
59 
60  m_registration.def(
61  "correspondences_from_features", &CorrespondencesFromFeatures,
62  py::call_guard<py::gil_scoped_release>(), "source_features"_a,
63  "target_features"_a, "mutual_filter"_a = false,
64  "mutual_consistency_ratio"_a = 0.1f,
65  R"(Function to query nearest neighbors of source_features in target_features.
66 
67 Args:
68  source_features (cloudViewer.core.Tensor): The source features in shape (N, dim).
69  target_features (cloudViewer.core.Tensor): The target features in shape (M, dim).
70  mutual_filter (bool, optional): Filter correspondences and return the
71  collection of (i, j) s.t. source_features[i] and target_features[j] are
72  mutually the nearest neighbor. Default is False.
73  mutual_consistency_ratio (float, optional): Threshold to decide whether the
74  number of filtered correspondences is sufficient. Only used when
75  `mutual_filter` is enabled. Default is 0.1.
76 
77 Returns:
78  Tensor with shape (K,2) of source_indices and target_indices with K as the
79  number of correspondences.
80 
81 Example:
82 
83  This example shows how to compute the features and correspondences for two point clouds::
84 
85  import cloudViewer as cv3d
86 
87  # read and downsample point clouds
88  paths = cv3d.data.DemoICPPointClouds().paths
89  voxel_size = 0.01
90  pcd1 = cv3d.t.io.read_point_cloud(paths[0]).voxel_down_sample(voxel_size)
91  pcd2 = cv3d.t.io.read_point_cloud(paths[1]).voxel_down_sample(voxel_size)
92 
93  # compute FPFH features
94  pcd1_fpfh = cv3d.t.pipelines.registration.compute_fpfh_feature(pcd1, radius=5*voxel_size)
95  pcd2_fpfh = cv3d.t.pipelines.registration.compute_fpfh_feature(pcd2, radius=5*voxel_size)
96 
97  # compute correspondences
98  matches = cv3d.t.pipelines.registration.correspondences_from_features(pcd1_fpfh, pcd2_fpfh, mutual_filter=True)
99 
100  # visualize correspondences
101  matches = matches[::500]
102  pcd2.translate([0,2,0]) # translate pcd2 for the visualization
103  lines = cv3d.t.geometry.LineSet()
104  lines.point.positions = cv3d.core.Tensor.zeros((matches.num_elements(), 3))
105  lines.point.positions[0::2] = pcd1.point.positions[matches[:,0]]
106  lines.point.positions[1::2] = pcd2.point.positions[matches[:,1]]
107  lines.line.indices = cv3d.core.Tensor.arange(matches.num_elements()).reshape((-1,2))
108 
109  cv3d.visualization.draw([pcd1, pcd2, lines])
110 
111 )");
112 }
113 
114 } // namespace registration
115 } // namespace pipelines
116 } // namespace t
117 } // namespace cloudViewer
core::Tensor ComputeFPFHFeature(const geometry::PointCloud &input, const utility::optional< int > max_nn, const utility::optional< double > radius, const utility::optional< core::Tensor > &indices)
Definition: Feature.cpp:23
core::Tensor CorrespondencesFromFeatures(const core::Tensor &source_features, const core::Tensor &target_features, bool mutual_filter, float mutual_consistent_ratio)
Function to find correspondences via 1-nearest neighbor feature matching. Target is used to construct...
Definition: Feature.cpp:280
void pybind_feature(py::module &m_registration)
Definition: feature.cpp:20
Generic file read and write utility for python interface.