Point Cloud Library (PCL)  1.14.1-dev
smoothed_surfaces_keypoint.hpp
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Alexandru-Eugen Ichim
5  * Willow Garage, Inc
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Willow Garage, Inc. nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * $Id$
36  */
37 
38 #ifndef PCL_KEYPOINTS_IMPL_SMOOTHEDSURFACESKEYPOINT_H_
39 #define PCL_KEYPOINTS_IMPL_SMOOTHEDSURFACESKEYPOINT_H_
40 
41 #include <pcl/keypoints/smoothed_surfaces_keypoint.h>
42 
43 //#include <pcl/io/pcd_io.h>
44 
45 //////////////////////////////////////////////////////////////////////////////////////////////
46 template <typename PointT, typename PointNT> void
48  const PointCloudNTConstPtr &normals,
49  KdTreePtr &kdtree,
50  float &scale)
51 {
52  clouds_.push_back (cloud);
53  cloud_normals_.push_back (normals);
54  cloud_trees_.push_back (kdtree);
55  scales_.emplace_back(scale, scales_.size ());
56 }
57 
58 
59 //////////////////////////////////////////////////////////////////////////////////////////////
60 template <typename PointT, typename PointNT> void
62 {
63  clouds_.clear ();
64  cloud_normals_.clear ();
65  scales_.clear ();
66 }
67 
68 
69 //////////////////////////////////////////////////////////////////////////////////////////////
70 template <typename PointT, typename PointNT> void
72 {
73  // Calculate differences for each cloud
74  std::vector<std::vector<float> > diffs (scales_.size ());
75 
76  // The cloud with the smallest scale has no differences
77  std::vector<float> aux_diffs (input_->size (), 0.0f);
78  diffs[scales_[0].second] = aux_diffs;
79 
80  cloud_trees_[scales_[0].second]->setInputCloud (clouds_[scales_[0].second]);
81  for (std::size_t scale_i = 1; scale_i < clouds_.size (); ++scale_i)
82  {
83  std::size_t cloud_i = scales_[scale_i].second,
84  cloud_i_minus_one = scales_[scale_i - 1].second;
85  diffs[cloud_i].resize (input_->size ());
86  PCL_INFO ("cloud_i %u cloud_i_minus_one %u\n", cloud_i, cloud_i_minus_one);
87  for (std::size_t point_i = 0; point_i < input_->size (); ++point_i)
88  diffs[cloud_i][point_i] = (*cloud_normals_[cloud_i])[point_i].getNormalVector3fMap ().dot (
89  (*clouds_[cloud_i])[point_i].getVector3fMap () - (*clouds_[cloud_i_minus_one])[point_i].getVector3fMap ());
90 
91  // Setup kdtree for this cloud
92  cloud_trees_[cloud_i]->setInputCloud (clouds_[cloud_i]);
93  }
94 
95 
96  // Find minima and maxima in differences inside the input cloud
97  typename pcl::search::Search<PointT>::Ptr input_tree = cloud_trees_.back ();
98  for (pcl::index_t point_i = 0; point_i < static_cast<pcl::index_t> (input_->size ()); ++point_i)
99  {
100  pcl::Indices nn_indices;
101  std::vector<float> nn_distances;
102  input_tree->radiusSearch (point_i, input_scale_ * neighborhood_constant_, nn_indices, nn_distances);
103 
104  bool is_min = true, is_max = true;
105  for (const auto &nn_index : nn_indices)
106  if (nn_index != point_i)
107  {
108  if (diffs[input_index_][point_i] < diffs[input_index_][nn_index])
109  is_max = false;
110  else if (diffs[input_index_][point_i] > diffs[input_index_][nn_index])
111  is_min = false;
112  }
113 
114  // If the point is a local minimum/maximum, check if it is the same over all the scales
115  if (is_min || is_max)
116  {
117  bool passed_min = true, passed_max = true;
118  for (const auto & scale : scales_)
119  {
120  std::size_t cloud_i = scale.second;
121  // skip input cloud
122  if (cloud_i == clouds_.size () - 1)
123  continue;
124 
125  nn_indices.clear (); nn_distances.clear ();
126  cloud_trees_[cloud_i]->radiusSearch (point_i, scale.first * neighborhood_constant_, nn_indices, nn_distances);
127 
128  bool is_min_other_scale = true, is_max_other_scale = true;
129  for (const auto &nn_index : nn_indices)
130  if (nn_index != point_i)
131  {
132  if (diffs[input_index_][point_i] < diffs[cloud_i][nn_index])
133  is_max_other_scale = false;
134  else if (diffs[input_index_][point_i] > diffs[cloud_i][nn_index])
135  is_min_other_scale = false;
136  }
137 
138  if (is_min && !is_min_other_scale)
139  passed_min = false;
140  if (is_max && !is_max_other_scale)
141  passed_max = false;
142 
143  if (!passed_min && !passed_max)
144  break;
145  }
146 
147  // check if point was minimum/maximum over all the scales
148  if (passed_min || passed_max)
149  {
150  output.push_back ((*input_)[point_i]);
151  keypoints_indices_->indices.push_back (point_i);
152  }
153  }
154  }
155 
156  output.header = input_->header;
157  output.width = output.size ();
158  output.height = 1;
159 
160  // debug stuff
161 // for (std::size_t scale_i = 0; scale_i < scales_.size (); ++scale_i)
162 // {
163 // PointCloud<PointXYZI>::Ptr debug_cloud (new PointCloud<PointXYZI> ());
164 // debug_cloud->points.resize (input_->size ());
165 // debug_cloud->width = input_->width;
166 // debug_cloud->height = input_->height;
167 // for (std::size_t point_i = 0; point_i < input_->size (); ++point_i)
168 // {
169 // (*debug_cloud)[point_i].intensity = diffs[scales_[scale_i].second][point_i];
170 // (*debug_cloud)[point_i].x = (*input_)[point_i].x;
171 // (*debug_cloud)[point_i].y = (*input_)[point_i].y;
172 // (*debug_cloud)[point_i].z = (*input_)[point_i].z;
173 // }
174 
175 // char str[512]; sprintf (str, "diffs_%2d.pcd", scale_i);
176 // io::savePCDFile (str, *debug_cloud);
177 // }
178 }
179 
180 //////////////////////////////////////////////////////////////////////////////////////////////
181 template <typename PointT, typename PointNT> bool
183 {
184  PCL_INFO ("SmoothedSurfacesKeypoint initCompute () called\n");
186  {
187  PCL_ERROR ("[pcl::SmoothedSurfacesKeypoints::initCompute] Keypoint::initCompute failed\n");
188  return false;
189  }
190 
191  if (!normals_)
192  {
193  PCL_ERROR ("[pcl::SmoothedSurfacesKeypoints::initCompute] Input normals were not set\n");
194  return false;
195  }
196  if (clouds_.empty ())
197  {
198  PCL_ERROR ("[pcl::SmoothedSurfacesKeypoints::initCompute] No other clouds were set apart from the input\n");
199  return false;
200  }
201 
202  if (input_->size () != normals_->size ())
203  {
204  PCL_ERROR ("[pcl::SmoothedSurfacesKeypoints::initCompute] The input cloud and the input normals differ in size\n");
205  return false;
206  }
207 
208  for (std::size_t cloud_i = 0; cloud_i < clouds_.size (); ++cloud_i)
209  {
210  if (clouds_[cloud_i]->size () != input_->size ())
211  {
212  PCL_ERROR("[pcl::SmoothedSurfacesKeypoints::initCompute] Cloud %zu does not have "
213  "the same number of points as the input cloud\n",
214  cloud_i);
215  return false;
216  }
217 
218  if (cloud_normals_[cloud_i]->size () != input_->size ())
219  {
220  PCL_ERROR("[pcl::SmoothedSurfacesKeypoints::initCompute] Normals for cloud %zu "
221  "do not have the same number of points as the input cloud\n",
222  cloud_i);
223  return false;
224  }
225  }
226 
227  // Add the input cloud as the last index
228  scales_.emplace_back(input_scale_, scales_.size ());
229  clouds_.push_back (input_);
230  cloud_normals_.push_back (normals_);
231  cloud_trees_.push_back (tree_);
232  // Sort the clouds by their scales
233  sort (scales_.begin (), scales_.end (), compareScalesFunction);
234 
235  // Find the index of the input after sorting
236  for (std::size_t i = 0; i < scales_.size (); ++i)
237  if (scales_[i].second == scales_.size () - 1)
238  {
239  input_index_ = i;
240  break;
241  }
242 
243  PCL_INFO ("Scales: ");
244  for (const auto & scale : scales_) PCL_INFO ("(%d %f), ", scale.second, scale.first);
245  PCL_INFO ("\n");
246 
247  return (true);
248 }
249 
250 
251 #define PCL_INSTANTIATE_SmoothedSurfacesKeypoint(T,NT) template class PCL_EXPORTS pcl::SmoothedSurfacesKeypoint<T,NT>;
252 
253 
254 #endif /* PCL_KEYPOINTS_IMPL_SMOOTHEDSURFACESKEYPOINT_H_ */
Keypoint represents the base class for key points.
Definition: keypoint.h:49
PointCloud represents the base class in PCL for storing collections of 3D points.
Definition: point_cloud.h:173
void push_back(const PointT &pt)
Insert a new point in the cloud, at the end of the container.
Definition: point_cloud.h:663
std::uint32_t width
The point cloud width (if organized as an image-structure).
Definition: point_cloud.h:398
pcl::PCLHeader header
The point cloud header.
Definition: point_cloud.h:392
std::uint32_t height
The point cloud height (if organized as an image-structure).
Definition: point_cloud.h:400
std::size_t size() const
Definition: point_cloud.h:443
typename PointCloudNT::ConstPtr PointCloudNTConstPtr
typename Keypoint< PointT, PointT >::KdTreePtr KdTreePtr
void addSmoothedPointCloud(const PointCloudTConstPtr &cloud, const PointCloudNTConstPtr &normals, KdTreePtr &kdtree, float &scale)
typename PointCloudT::ConstPtr PointCloudTConstPtr
void detectKeypoints(PointCloudT &output) override
shared_ptr< pcl::search::Search< PointT > > Ptr
Definition: search.h:81
virtual int radiusSearch(const PointT &point, double radius, Indices &k_indices, std::vector< float > &k_sqr_distances, unsigned int max_nn=0) const =0
Search for all the nearest neighbors of the query point in a given radius.
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
Definition: types.h:112
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition: types.h:133