NDEVR
API Documentation
NDEVRCorrespondenceEstimation.h
1#pragma once
2#include <NDEVR/RTree.h>
3#include <NDEVR/Buffer.h>
4#include <NDEVR/LineSegment.h>
5#include <NDEVR/Distance.h>
6#include <pcl/registration/correspondence_types.h>
7namespace NDEVR
8{
9 using namespace pcl;
10 using namespace pcl::registration;
16 template <typename PointSource,
17 typename PointTarget,
18 typename NormalT,
19 typename Scalar = float>
21 {
22 public:
23 using Ptr = shared_ptr<NDEVRCorrespondenceEstimation<PointSource,
24 PointTarget,
25 NormalT,
26 Scalar>>;
27 using ConstPtr = shared_ptr<const NDEVRCorrespondenceEstimation<PointSource,
28 PointTarget,
29 NormalT,
30 Scalar>>;
31
32
33 using PointCloudSource = pcl::PointCloud<PointSource>;
34 using PointCloudSourcePtr = typename PointCloudSource::Ptr;
35 using PointCloudSourceConstPtr = typename PointCloudSource::ConstPtr;
36
37 using PointCloudTarget = pcl::PointCloud<PointTarget>;
38 using PointCloudTargetPtr = typename PointCloudTarget::Ptr;
39 using PointCloudTargetConstPtr = typename PointCloudTarget::ConstPtr;
40
41 using PointCloudNormals = pcl::PointCloud<NormalT>;
42 using NormalsPtr = typename PointCloudNormals::Ptr;
43 using NormalsConstPtr = typename PointCloudNormals::ConstPtr;
50 : source_normals_()
51 , source_normals_transformed_()
52 , target_normals_()
53 {}
54
56 virtual ~NDEVRCorrespondenceEstimation() = default;
57
63 void setTree(const RTree<3, fltp04>* tree, const Buffer<Vertex<3, fltp04>>* params, const Buffer<Vertex<3, fltp04>>* tree_sorted_params)
64 {
65 m_tree = tree;
66 m_params = params;
67 m_tree_sorted_params = tree_sorted_params;
68 }
69
72 inline void setSourceNormals(const NormalsConstPtr& normals)
73 {
74 source_normals_ = normals;
75 }
76
79 inline NormalsConstPtr getSourceNormals() const
80 {
81 return (source_normals_);
82 }
83
87 inline void setTargetNormals(const NormalsConstPtr& normals)
88 {
89 target_normals_ = normals;
90 }
91
94 inline NormalsConstPtr getTargetNormals() const
95 {
96 return (target_normals_);
97 }
98
101 {
102 return (true);
103 }
104
107 void setInputTarget(PointCloudSourcePtr input)
108 {
109 input_ = input;
110 }
111
113 void setSourceNormals(pcl::PCLPointCloud2::ConstPtr cloud2)
114 {
115 NormalsPtr cloud(new PointCloudNormals);
116 fromPCLPointCloud2(*cloud2, *cloud);
117 setSourceNormals(cloud);
118 }
119
122 {
123 return (true);
124 }
125
127 void setTargetNormals(pcl::PCLPointCloud2::ConstPtr cloud2)
128 {
129 NormalsPtr cloud(new PointCloudNormals);
130 fromPCLPointCloud2(*cloud2, *cloud);
131 setTargetNormals(cloud);
132 }
133
145 {
146 const auto& pt = input_->at(index);
147 return Vertex<3, fltp04>(pt.x, pt.y, pt.z);
148 }
149
154 {
156 const auto& pt = input_->at(index);
157 ls[A] = Vertex<3, fltp04>(pt.x, pt.y, pt.z);
158 Vertex<3, fltp04> nm((*target_normals_)[index].normal_x
159 , (*target_normals_)[index].normal_y
160 , (*target_normals_)[index].normal_z);
161 ls[B] = ls[A] + m_normal_expansion_factor * nm;
162 ls[A] = ls[A] - m_normal_expansion_factor * nm;
163 return ls;
164 }
165
171 bool radiusSearch(uint04 tgt_idx, uint04& index, fltp04& k_sqr_distances) const
172 {
173 Vertex<3, fltp04> vert = vertex(tgt_idx);
174 index = m_tree->closestElementPresorted(vert, *m_tree_sorted_params, k_sqr_distances, m_epsilon);
175 if (IsInvalid(index))
176 return false;
177 index = m_tree->indices()[index];
178 return true;
179 }
180
186 bool radiusNormalSearch(uint04 tgt_idx, uint04& index, fltp04& k_sqr_distances) const
187 {
188 LineSegment<3, fltp04> seg = lineSegment(tgt_idx);
189 index = m_tree->closestElementPresorted(seg, *m_tree_sorted_params, k_sqr_distances, m_epsilon);
190 if (IsInvalid(index))
191 return false;
192 index = m_tree->indices()[index];
193 return true;
194 }
195
201 MaxHeap<fltp04, uint04> radiusKSearch(uint04 tgt_idx, fltp04 max_distance_squared, uint04 k = 0) const
202 {
203 Vertex<3, fltp04> vert = vertex(tgt_idx);
204 //vertex = m_input_transform * vertex;
205 MaxHeap<fltp04, uint04> heap(cast<uint04>(k + 1));
206 m_tree->presortedClosestElements(vert, k, heap, *m_tree_sorted_params, max_distance_squared, m_epsilon);
207 const uint04 size = heap.size();
208 //auto sorted_values = heap.sortedValues();
209 for (uint04 i = 0; i < size; i++)
210 heap.values()[i].first = m_tree->indices()[heap.values()[i].first];
211 return heap;
212 }
213
219 MaxHeap<fltp04, uint04> radiusNormalKSearch(uint04 tgt_idx, fltp04 max_distance_squared, uint04 k = 0) const
220 {
221 LineSegment<3, fltp04> seg = lineSegment(tgt_idx);
222 //vertex = m_input_transform * vertex;
223 MaxHeap<fltp04, uint04> heap(cast<uint04>(k + 1));
224 m_tree->presortedClosestElements(seg, k, heap, *m_tree_sorted_params, max_distance_squared, m_epsilon);
225 const uint04 size = heap.size();
226 //auto sorted_values = heap.sortedValues();
227 for (uint04 i = 0; i < size; i++)
228 heap.values()[i].first = m_tree->indices()[heap.values()[i].first];
229 return heap;
230 }
231
237 {
238 fltp04 d = distance<fltp04>(vertex(a), (*m_params)[b]);
239 fltp04 cos_angle = (*source_normals_)[b].normal_x *
240 (*target_normals_)[a].normal_x +
241 (*source_normals_)[b].normal_y *
242 (*target_normals_)[a].normal_y +
243 (*source_normals_)[b].normal_z *
244 (*target_normals_)[a].normal_z;
245 return d * (2.0f - cos_angle * cos_angle);
246 }
247
252 void determineCorrespondencesMinDistance(uint04 offset, pcl::Correspondences& correspondences, fltp04 max_distance)
253 {
254 // Iterate over the input set of source indices
255 int count = input_->size();
256 correspondences.clear();
257 //#pragma omp parallel for schedule(dynamic) num_threads(8)
258 for (int idx_i = offset; idx_i < count; idx_i += m_skip_factor)
259 {
260 uint04 idx;
261 fltp04 dist = max_distance;
262 if (radiusSearch(idx_i, idx, dist))
263 {
264 if (dist <= max_distance)
265 {
266 pcl::Correspondence corr;
267 corr.index_query = idx_i;
268 corr.index_match = idx;
269 corr.distance = dist;
270 correspondences.push_back(corr);
271 }
272 }
273 }
274 }
275
280 void determineCorrespondencesBackProjection(uint04 offset, pcl::Correspondences& correspondences, fltp04 max_distance)
281 {
282 // Iterate over the input set of source indices
283 int count = input_->size();
284 correspondences.clear();
285 //#pragma omp parallel for schedule(dynamic) num_threads(8)
286 for (int idx_i = offset; idx_i < count; idx_i += m_skip_factor)
287 {
288
289 if (k_ == 1)
290 {
291 uint04 idx;
292 fltp04 dist = max_distance;
293 if (radiusNormalSearch(idx_i, idx, dist))
294 {
295 fltp04 distance = calcDistance(idx_i, idx);
296 if (distance <= max_distance)
297 {
298 pcl::Correspondence corr;
299 corr.index_query = idx_i;
300 corr.index_match = idx;
301 corr.distance = distance;
302 correspondences.push_back(corr);
303 }
304 }
305 }
306 else
307 {
308 MinHeap<fltp04, uint04> heap = radiusNormalKSearch(idx_i, max_distance, k_);
309 const uint04 size = heap.size();
310 if (size == 0)
311 continue;
312 uint04 min_index = heap.values()[0].first;
313 fltp04 min_dist = calcDistance(idx_i, min_index);
314 for (uint04 i = 1; i < size; i++)
315 {
316 float dist = calcDistance(idx_i, heap.values()[i].first);
317 if (dist < min_dist)
318 {
319 min_dist = dist;
320 min_index = heap.values()[i].first;
321 }
322 }
323 if (min_dist <= max_distance)
324 {
325 pcl::Correspondence corr;
326 corr.index_query = idx_i;
327 corr.index_match = min_index;
328 corr.distance = min_dist;
329 correspondences.push_back(corr);
330 }
331 }
332 }
333 }
334
340 inline void setKSearch(unsigned int k)
341 {
342 k_ = k;
343 }
344
348 inline unsigned int getKSearch() const
349 {
350 return (k_);
351 }
352 private:
353 const RTree<3, fltp04>* m_tree;
354 const Buffer<Vertex<3, fltp04>>* m_params;
355 const Buffer<Vertex<3, fltp04>>* m_tree_sorted_params;
356 fltp04 m_normal_expansion_factor = 0.1f;
358 NormalsConstPtr source_normals_;
359
361 NormalsPtr source_normals_transformed_;
362 PointCloudSourcePtr input_;
363
365 PointCloudSourcePtr source_cloud_transformed_;
366
368 NormalsConstPtr target_normals_;
369 fltp04 m_epsilon = 0.0f;
370
372 uint04 k_{ 10 };
373 int m_skip_factor = 5;
374 };
375}
The equivelent of std::vector but with a bit more control.
Definition Buffer.hpp:58
Class: LineSegment.
Definition Line.hpp:52
void determineCorrespondencesMinDistance(uint04 offset, pcl::Correspondences &correspondences, fltp04 max_distance)
Determine correspondences using minimum distance search.
MaxHeap< fltp04, uint04 > radiusNormalKSearch(uint04 tgt_idx, fltp04 max_distance_squared, uint04 k=0) const
Find k closest points using normal-expanded line segment search within a max distance.
void determineCorrespondencesBackProjection(uint04 offset, pcl::Correspondences &correspondences, fltp04 max_distance)
Determine correspondences using back-projection along normals.
void setTargetNormals(pcl::PCLPointCloud2::ConstPtr cloud2)
Method for setting the target normals.
void setTree(const RTree< 3, fltp04 > *tree, const Buffer< Vertex< 3, fltp04 > > *params, const Buffer< Vertex< 3, fltp04 > > *tree_sorted_params)
Set the spatial search tree and associated point data.
void setSourceNormals(pcl::PCLPointCloud2::ConstPtr cloud2)
Blob method for setting the source normals.
NormalsConstPtr getTargetNormals() const
Get the normals of the target point cloud.
void setTargetNormals(const NormalsConstPtr &normals)
Set the normals computed on the target point cloud.
fltp04 calcDistance(uint04 a, uint04 b) const
Calculate the weighted distance between two points, factoring in normal alignment.
bool radiusSearch(uint04 tgt_idx, uint04 &index, fltp04 &k_sqr_distances) const
Find the closest point in the tree to the target point.
bool radiusNormalSearch(uint04 tgt_idx, uint04 &index, fltp04 &k_sqr_distances) const
Find the closest point in the tree using normal-expanded line segment search.
virtual ~NDEVRCorrespondenceEstimation()=default
Empty destructor.
void setSourceNormals(const NormalsConstPtr &normals)
Set the normals computed on the source point cloud.
void setKSearch(unsigned int k)
Set the number of nearest neighbours to be considered in the target point cloud.
bool requiresSourceNormals() const
See if this rejector requires source normals.
void setInputTarget(PointCloudSourcePtr input)
Set the input target point cloud.
LineSegment< 3, fltp04 > lineSegment(uint04 index) const
Returns a line segment along the normal at the given index, expanded by m_normal_expansion_factor.
MaxHeap< fltp04, uint04 > radiusKSearch(uint04 tgt_idx, fltp04 max_distance_squared, uint04 k=0) const
Find k closest points within a maximum distance.
bool requiresTargetNormals() const
See if this rejector requires target normals.
unsigned int getKSearch() const
Get the number of nearest neighbours considered in the target point cloud for computing correspondenc...
NormalsConstPtr getSourceNormals() const
Get the normals of the source point cloud.
Vertex< 3, fltp04 > vertex(uint04 index) const
Determine the correspondences between input and target cloud.
A point in N-dimensional space, used primarily for spatial location information.
Definition Vertex.hpp:44
The primary namespace for the NDEVR SDK.
float fltp04
Defines an alias representing a 4 byte floating-point number Bit layout is as follows: -Sign: 1 bit a...
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
static constexpr bool IsInvalid(const Angle< t_type > &value)
Checks whether the given Angle holds an invalid value.
Definition Angle.h:388
constexpr t_to cast(const Angle< t_from > &value)
Casts an Angle from one backing type to another.
Definition Angle.h:408