Point Cloud Library (PCL)  1.15.1-dev
shot_omp.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2009, Willow Garage, Inc.
6  * Copyright (c) 2012-, Open Perception, Inc.
7  *
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  *
14  * * Redistributions of source code must retain the above copyright
15  * notice, this list of conditions and the following disclaimer.
16  * * Redistributions in binary form must reproduce the above
17  * copyright notice, this list of conditions and the following
18  * disclaimer in the documentation and/or other materials provided
19  * with the distribution.
20  * * Neither the name of the copyright holder(s) nor the names of its
21  * contributors may be used to endorse or promote products derived
22  * from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  *
38  */
39 
40 #pragma once
41 
42 #include <pcl/features/shot_omp.h>
43 
44 #include <pcl/common/point_tests.h> // for pcl::isFinite
45 #include <pcl/common/time.h>
46 #include <pcl/features/shot_lrf_omp.h>
47 
48 
49 template<typename PointInT, typename PointNT, typename PointOutT, typename PointRFT> bool
51 {
53  {
54  PCL_ERROR ("[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
55  return (false);
56  }
57 
58  // SHOT cannot work with k-search
59  if (this->getKSearch () != 0)
60  {
61  PCL_ERROR(
62  "[pcl::%s::initCompute] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
63  getClassName().c_str ());
64  return (false);
65  }
66 
67  // Default LRF estimation alg: SHOTLocalReferenceFrameEstimationOMP
69  lrf_estimator->setRadiusSearch ((lrf_radius_ > 0 ? lrf_radius_ : search_radius_));
70  lrf_estimator->setInputCloud (input_);
71  lrf_estimator->setIndices (indices_);
72  lrf_estimator->setNumberOfThreads(threads_);
73 
74  if (!fake_surface_)
75  lrf_estimator->setSearchSurface(surface_);
76 
78  {
79  PCL_ERROR ("[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
80  return (false);
81  }
82 
83  return (true);
84 }
85 
86 //////////////////////////////////////////////////////////////////////////////////////////////
87 template<typename PointInT, typename PointNT, typename PointOutT, typename PointRFT> bool
89 {
91  {
92  PCL_ERROR ("[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
93  return (false);
94  }
95 
96  // SHOT cannot work with k-search
97  if (this->getKSearch () != 0)
98  {
99  PCL_ERROR(
100  "[pcl::%s::initCompute] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
101  getClassName().c_str ());
102  return (false);
103  }
104 
105  // Default LRF estimation alg: SHOTLocalReferenceFrameEstimationOMP
107  lrf_estimator->setRadiusSearch ((lrf_radius_ > 0 ? lrf_radius_ : search_radius_));
108  lrf_estimator->setInputCloud (input_);
109  lrf_estimator->setIndices (indices_);
110  lrf_estimator->setNumberOfThreads(threads_);
111 
112  if (!fake_surface_)
113  lrf_estimator->setSearchSurface(surface_);
114 
116  {
117  PCL_ERROR ("[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
118  return (false);
119  }
120 
121  return (true);
122 }
123 
124 //////////////////////////////////////////////////////////////////////////////////////////////
125 template<typename PointInT, typename PointNT, typename PointOutT, typename PointRFT> void
127 {
128  if (nr_threads == 0)
129 #ifdef _OPENMP
130  threads_ = omp_get_num_procs();
131 #else
132  threads_ = 1;
133 #endif
134  else
135  threads_ = nr_threads;
136 }
137 
138 //////////////////////////////////////////////////////////////////////////////////////////////
139 template<typename PointInT, typename PointNT, typename PointOutT, typename PointRFT> void
141 {
142  descLength_ = nr_grid_sector_ * (nr_shape_bins_ + 1);
143 
144  sqradius_ = search_radius_ * search_radius_;
145  radius3_4_ = (search_radius_ * 3) / 4;
146  radius1_4_ = search_radius_ / 4;
147  radius1_2_ = search_radius_ / 2;
148 
149  assert(descLength_ == 352);
150 
151  output.is_dense = true;
152  // Iterating over the entire index vector
153 #pragma omp parallel for \
154  default(none) \
155  shared(output) \
156  num_threads(threads_) \
157  schedule(dynamic, chunk_size_)
158  for (std::ptrdiff_t idx = 0; idx < static_cast<std::ptrdiff_t> (indices_->size ()); ++idx)
159  {
160 
161  Eigen::VectorXf shot;
162  shot.setZero (descLength_);
163 
164  bool lrf_is_nan = false;
165  const PointRFT& current_frame = (*frames_)[idx];
166  if (!std::isfinite (current_frame.x_axis[0]) ||
167  !std::isfinite (current_frame.y_axis[0]) ||
168  !std::isfinite (current_frame.z_axis[0]))
169  {
170  PCL_WARN ("[pcl::%s::computeFeature] The local reference frame is not valid! Aborting description of point with index %d\n",
171  getClassName ().c_str (), (*indices_)[idx]);
172  lrf_is_nan = true;
173  }
174 
175  // Allocate enough space to hold the results
176  // \note This resize is irrelevant for a radiusSearch ().
177  pcl::Indices nn_indices (k_);
178  std::vector<float> nn_dists (k_);
179 
180  if (!isFinite ((*input_)[(*indices_)[idx]]) || lrf_is_nan || this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices,
181  nn_dists) == 0)
182  {
183  // Copy into the resultant cloud
184  for (Eigen::Index d = 0; d < shot.size (); ++d)
185  output[idx].descriptor[d] = std::numeric_limits<float>::quiet_NaN ();
186  for (int d = 0; d < 9; ++d)
187  output[idx].rf[d] = std::numeric_limits<float>::quiet_NaN ();
188 
189  output.is_dense = false;
190  continue;
191  }
192 
193  // Estimate the SHOT at each patch
194  this->computePointSHOT (idx, nn_indices, nn_dists, shot);
195 
196  // Copy into the resultant cloud
197  for (Eigen::Index d = 0; d < shot.size (); ++d)
198  output[idx].descriptor[d] = shot[d];
199  for (int d = 0; d < 3; ++d)
200  {
201  output[idx].rf[d + 0] = (*frames_)[idx].x_axis[d];
202  output[idx].rf[d + 3] = (*frames_)[idx].y_axis[d];
203  output[idx].rf[d + 6] = (*frames_)[idx].z_axis[d];
204  }
205  }
206 }
207 
208 //////////////////////////////////////////////////////////////////////////////////////////////
209 template <typename PointInT, typename PointNT, typename PointOutT, typename PointRFT> void
211 {
212  if (nr_threads == 0)
213 #ifdef _OPENMP
214  threads_ = omp_get_num_procs();
215 #else
216  threads_ = 1;
217 #endif
218  else
219  threads_ = nr_threads;
220 }
221 
222 //////////////////////////////////////////////////////////////////////////////////////////////
223 template <typename PointInT, typename PointNT, typename PointOutT, typename PointRFT> void
225 {
226  descLength_ = (b_describe_shape_) ? nr_grid_sector_ * (nr_shape_bins_ + 1) : 0;
227  descLength_ += (b_describe_color_) ? nr_grid_sector_ * (nr_color_bins_ + 1) : 0;
228 
229  assert( (!b_describe_color_ && b_describe_shape_ && descLength_ == 352) ||
230  (b_describe_color_ && !b_describe_shape_ && descLength_ == 992) ||
231  (b_describe_color_ && b_describe_shape_ && descLength_ == 1344)
232  );
233 
234  sqradius_ = search_radius_ * search_radius_;
235  radius3_4_ = (search_radius_ * 3) / 4;
236  radius1_4_ = search_radius_ / 4;
237  radius1_2_ = search_radius_ / 2;
238 
239  output.is_dense = true;
240  // Iterating over the entire index vector
241 #pragma omp parallel for \
242  default(none) \
243  shared(output) \
244  num_threads(threads_) \
245  schedule(dynamic, chunk_size_)
246  for (std::ptrdiff_t idx = 0; idx < static_cast<std::ptrdiff_t> (indices_->size ()); ++idx)
247  {
248  Eigen::VectorXf shot;
249  shot.setZero (descLength_);
250 
251  // Allocate enough space to hold the results
252  // \note This resize is irrelevant for a radiusSearch ().
253  pcl::Indices nn_indices (k_);
254  std::vector<float> nn_dists (k_);
255 
256  bool lrf_is_nan = false;
257  const PointRFT& current_frame = (*frames_)[idx];
258  if (!std::isfinite (current_frame.x_axis[0]) ||
259  !std::isfinite (current_frame.y_axis[0]) ||
260  !std::isfinite (current_frame.z_axis[0]))
261  {
262  PCL_WARN ("[pcl::%s::computeFeature] The local reference frame is not valid! Aborting description of point with index %d\n",
263  getClassName ().c_str (), (*indices_)[idx]);
264  lrf_is_nan = true;
265  }
266 
267  if (!isFinite ((*input_)[(*indices_)[idx]]) ||
268  lrf_is_nan ||
269  this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists) == 0)
270  {
271  // Copy into the resultant cloud
272  for (Eigen::Index d = 0; d < shot.size (); ++d)
273  output[idx].descriptor[d] = std::numeric_limits<float>::quiet_NaN ();
274  for (int d = 0; d < 9; ++d)
275  output[idx].rf[d] = std::numeric_limits<float>::quiet_NaN ();
276 
277  output.is_dense = false;
278  continue;
279  }
280 
281  // Estimate the SHOT at each patch
282  this->computePointSHOT (idx, nn_indices, nn_dists, shot);
283 
284  // Copy into the resultant cloud
285  for (Eigen::Index d = 0; d < shot.size (); ++d)
286  output[idx].descriptor[d] = shot[d];
287  for (int d = 0; d < 3; ++d)
288  {
289  output[idx].rf[d + 0] = (*frames_)[idx].x_axis[d];
290  output[idx].rf[d + 3] = (*frames_)[idx].y_axis[d];
291  output[idx].rf[d + 6] = (*frames_)[idx].z_axis[d];
292  }
293  }
294 }
295 
296 #define PCL_INSTANTIATE_SHOTEstimationOMP(T,NT,OutT,RFT) template class PCL_EXPORTS pcl::SHOTEstimationOMP<T,NT,OutT,RFT>;
297 #define PCL_INSTANTIATE_SHOTColorEstimationOMP(T,NT,OutT,RFT) template class PCL_EXPORTS pcl::SHOTColorEstimationOMP<T,NT,OutT,RFT>;
298 
void setSearchSurface(const PointCloudInConstPtr &cloud)
Provide a pointer to a dataset to add additional information to estimate the features for every point...
Definition: feature.h:146
void setRadiusSearch(double radius)
Set the sphere radius that is to be used for determining the nearest neighbors used for the feature e...
Definition: feature.h:198
FeatureWithLocalReferenceFrames provides a public interface for descriptor extractor classes which ne...
Definition: feature.h:440
virtual void setInputCloud(const PointCloudConstPtr &cloud)
Provide a pointer to the input dataset.
Definition: pcl_base.hpp:65
virtual void setIndices(const IndicesPtr &indices)
Provide a pointer to the vector of indices that represents the input data.
Definition: pcl_base.hpp:72
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
Definition: point_cloud.h:404
void setNumberOfThreads(unsigned int nr_threads=0)
Initialize the scheduler and set the number of threads to use.
Definition: shot_omp.hpp:210
void computeFeature(PointCloudOut &output) override
Estimate the Signatures of Histograms of OrienTations (SHOT) descriptors at a set of points given by ...
Definition: shot_omp.hpp:224
bool initCompute() override
This method should get called before starting the actual computation.
Definition: shot_omp.hpp:88
void setNumberOfThreads(unsigned int nr_threads=0)
Initialize the scheduler and set the number of threads to use.
Definition: shot_omp.hpp:126
bool initCompute() override
This method should get called before starting the actual computation.
Definition: shot_omp.hpp:50
void computeFeature(PointCloudOut &output) override
Estimate the Signatures of Histograms of OrienTations (SHOT) descriptors at a set of points given by ...
Definition: shot_omp.hpp:140
SHOTLocalReferenceFrameEstimation estimates the Local Reference Frame used in the calculation of the ...
Definition: shot_lrf_omp.h:67
shared_ptr< SHOTLocalReferenceFrameEstimationOMP< PointInT, PointOutT > > Ptr
Definition: shot_lrf_omp.h:69
void setNumberOfThreads(unsigned int nr_threads=0)
Initialize the scheduler and set the number of threads to use.
Define methods for measuring time spent in code blocks.
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
Definition: point_tests.h:56
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133