Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
multiscale_feature_persistence.hpp
Go to the documentation of this file.
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: multiscale_feature_persistence.hpp 5026 2012-03-12 02:51:44Z rusu $
36  */
37 
38 #ifndef PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_
39 #define PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_
40 
42 
44 template <typename PointSource, typename PointFeature>
46  scale_values_ (),
47  alpha_ (0),
48  distance_metric_ (L1),
49  feature_estimator_ (),
50  features_at_scale_ (),
51  features_at_scale_vectorized_ (),
52  mean_feature_ (),
53  feature_representation_ (),
54  unique_features_indices_ (),
55  unique_features_table_ ()
56 {
57  feature_representation_.reset (new DefaultPointRepresentation<PointFeature>);
58  // No input is needed, hack around the initCompute () check from PCLBase
59  input_.reset (new pcl::PointCloud<PointSource> ());
60 }
61 
62 
64 template <typename PointSource, typename PointFeature> bool
66 {
68  {
69  PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] PCLBase::initCompute () failed - no input cloud was given.\n");
70  return false;
71  }
72  if (!feature_estimator_)
73  {
74  PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] No feature estimator was set\n");
75  return false;
76  }
77  if (scale_values_.empty ())
78  {
79  PCL_ERROR ("[pcl::MultiscaleFeaturePersistence::initCompute] No scale values were given\n");
80  return false;
81  }
82 
83  mean_feature_.resize (feature_representation_->getNumberOfDimensions ());
84 
85  return true;
86 }
87 
88 
90 template <typename PointSource, typename PointFeature> void
92 {
93  features_at_scale_.resize (scale_values_.size ());
94  features_at_scale_vectorized_.resize (scale_values_.size ());
95  for (size_t scale_i = 0; scale_i < scale_values_.size (); ++scale_i)
96  {
97  FeatureCloudPtr feature_cloud (new FeatureCloud ());
98  computeFeatureAtScale (scale_values_[scale_i], feature_cloud);
99  features_at_scale_[scale_i] = feature_cloud;
100 
101  // Vectorize each feature and insert it into the vectorized feature storage
102  std::vector<std::vector<float> > feature_cloud_vectorized (feature_cloud->points.size ());
103  for (size_t feature_i = 0; feature_i < feature_cloud->points.size (); ++feature_i)
104  {
105  std::vector<float> feature_vectorized (feature_representation_->getNumberOfDimensions ());
106  feature_representation_->vectorize (feature_cloud->points[feature_i], feature_vectorized);
107  feature_cloud_vectorized[feature_i] = feature_vectorized;
108  }
109  features_at_scale_vectorized_[scale_i] = feature_cloud_vectorized;
110  }
111 }
112 
113 
115 template <typename PointSource, typename PointFeature> void
117  FeatureCloudPtr &features)
118 {
119  feature_estimator_->setRadiusSearch (scale);
120  feature_estimator_->compute (*features);
121 }
122 
123 
125 template <typename PointSource, typename PointFeature> float
127  const std::vector<float> &b)
128 {
129  return (pcl::selectNorm<std::vector<float> > (a, b, static_cast<int> (a.size ()), distance_metric_));
130 }
131 
132 
134 template <typename PointSource, typename PointFeature> void
136 {
137  // Reset mean feature
138  for (int i = 0; i < feature_representation_->getNumberOfDimensions (); ++i)
139  mean_feature_[i] = 0.0f;
140 
141  float normalization_factor = 0.0f;
142  for (std::vector<std::vector<std::vector<float> > >::iterator scale_it = features_at_scale_vectorized_.begin (); scale_it != features_at_scale_vectorized_.end(); ++scale_it) {
143  normalization_factor += static_cast<float> (scale_it->size ());
144  for (std::vector<std::vector<float> >::iterator feature_it = scale_it->begin (); feature_it != scale_it->end (); ++feature_it)
145  for (int dim_i = 0; dim_i < feature_representation_->getNumberOfDimensions (); ++dim_i)
146  mean_feature_[dim_i] += (*feature_it)[dim_i];
147  }
148 
149  for (int dim_i = 0; dim_i < feature_representation_->getNumberOfDimensions (); ++dim_i)
150  mean_feature_[dim_i] /= normalization_factor;
151 }
152 
153 
155 template <typename PointSource, typename PointFeature> void
157 {
158  unique_features_indices_.resize (scale_values_.size ());
159  unique_features_table_.resize (scale_values_.size ());
160  for (size_t scale_i = 0; scale_i < features_at_scale_vectorized_.size (); ++scale_i)
161  {
162  // Calculate standard deviation within the scale
163  float standard_dev = 0.0;
164  std::vector<float> diff_vector (features_at_scale_vectorized_[scale_i].size ());
165  for (size_t point_i = 0; point_i < features_at_scale_vectorized_[scale_i].size (); ++point_i)
166  {
167  float diff = distanceBetweenFeatures (features_at_scale_vectorized_[scale_i][point_i], mean_feature_);
168  standard_dev += diff * diff;
169  diff_vector[point_i] = diff;
170  }
171  standard_dev = sqrtf (standard_dev / static_cast<float> (features_at_scale_vectorized_[scale_i].size ()));
172  PCL_DEBUG ("[pcl::MultiscaleFeaturePersistence::extractUniqueFeatures] Standard deviation for scale %f is %f\n", scale_values_[scale_i], standard_dev);
173 
174  // Select only points outside (mean +/- alpha * standard_dev)
175  std::list<size_t> indices_per_scale;
176  std::vector<bool> indices_table_per_scale (features_at_scale_[scale_i]->points.size (), false);
177  for (size_t point_i = 0; point_i < features_at_scale_[scale_i]->points.size (); ++point_i)
178  {
179  if (diff_vector[point_i] > alpha_ * standard_dev)
180  {
181  indices_per_scale.push_back (point_i);
182  indices_table_per_scale[point_i] = true;
183  }
184  }
185  unique_features_indices_[scale_i] = indices_per_scale;
186  unique_features_table_[scale_i] = indices_table_per_scale;
187  }
188 }
189 
190 
192 template <typename PointSource, typename PointFeature> void
194  boost::shared_ptr<std::vector<int> > &output_indices)
195 {
196  if (!initCompute ())
197  return;
198 
199  // Compute the features for all scales with the given feature estimator
200  PCL_DEBUG ("[pcl::MultiscaleFeaturePersistence::determinePersistentFeatures] Computing features ...\n");
201  computeFeaturesAtAllScales ();
202 
203  // Compute mean feature
204  PCL_DEBUG ("[pcl::MultiscaleFeaturePersistence::determinePersistentFeatures] Calculating mean feature ...\n");
205  calculateMeanFeature ();
206 
207  // Get the 'unique' features at each scale
208  PCL_DEBUG ("[pcl::MultiscaleFeaturePersistence::determinePersistentFeatures] Extracting unique features ...\n");
209  extractUniqueFeatures ();
210 
211  PCL_DEBUG ("[pcl::MultiscaleFeaturePersistence::determinePersistentFeatures] Determining persistent features between scales ...\n");
212  // Determine persistent features between scales
213 
214 /*
215  // Method 1: a feature is considered persistent if it is 'unique' in at least 2 different scales
216  for (size_t scale_i = 0; scale_i < features_at_scale_vectorized_.size () - 1; ++scale_i)
217  for (std::list<size_t>::iterator feature_it = unique_features_indices_[scale_i].begin (); feature_it != unique_features_indices_[scale_i].end (); ++feature_it)
218  {
219  if (unique_features_table_[scale_i][*feature_it] == true)
220  {
221  output_features.points.push_back (features_at_scale[scale_i]->points[*feature_it]);
222  output_indices->push_back (feature_estimator_->getIndices ()->at (*feature_it));
223  }
224  }
225 */
226  // Method 2: a feature is considered persistent if it is 'unique' in all the scales
227  for (std::list<size_t>::iterator feature_it = unique_features_indices_.front ().begin (); feature_it != unique_features_indices_.front ().end (); ++feature_it)
228  {
229  bool present_in_all = true;
230  for (size_t scale_i = 0; scale_i < features_at_scale_.size (); ++scale_i)
231  present_in_all = present_in_all && unique_features_table_[scale_i][*feature_it];
232 
233  if (present_in_all)
234  {
235  output_features.points.push_back (features_at_scale_.front ()->points[*feature_it]);
236  output_indices->push_back (feature_estimator_->getIndices ()->at (*feature_it));
237  }
238  }
239 
240  // Consider that output cloud is unorganized
241  output_features.header = feature_estimator_->getInputCloud ()->header;
242  output_features.is_dense = feature_estimator_->getInputCloud ()->is_dense;
243  output_features.width = static_cast<uint32_t> (output_features.points.size ());
244  output_features.height = 1;
245 }
246 
247 
248 #define PCL_INSTANTIATE_MultiscaleFeaturePersistence(InT, Feature) template class PCL_EXPORTS pcl::MultiscaleFeaturePersistence<InT, Feature>;
249 
250 #endif /* PCL_FEATURES_IMPL_MULTISCALE_FEATURE_PERSISTENCE_H_ */