Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
statistical_multiscale_interest_region_extraction.hpp
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2011, Alexandru-Eugen Ichim
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 * $Id$
38 */
39
40#ifndef PCL_FEATURES_IMPL_STATISTICAL_MULTISCALE_INTEREST_REGION_EXTRACTION_H_
41#define PCL_FEATURES_IMPL_STATISTICAL_MULTISCALE_INTEREST_REGION_EXTRACTION_H_
42
43#include <pcl/features/statistical_multiscale_interest_region_extraction.h>
44#include <pcl/search/auto.h>
46#include <pcl/console/print.h> // for PCL_INFO, PCL_ERROR
47#include <boost/graph/adjacency_list.hpp>
48#include <boost/graph/johnson_all_pairs_shortest.hpp>
49
50
51//////////////////////////////////////////////////////////////////////////////////////////////
52template <typename PointT> void
54{
55 // generate a K-NNG (K-nearest neighbors graph)
56 typename pcl::search::Search<PointT>::Ptr kdtree(pcl::search::autoSelectMethod<PointT> (input_, true, pcl::search::Purpose::many_knn_search));
57
58 using namespace boost;
59 using Weight = property<edge_weight_t, float>;
60 using Graph = adjacency_list<vecS, vecS, undirectedS, no_property, Weight>;
61 Graph cloud_graph;
62
63 for (std::size_t point_i = 0; point_i < input_->size (); ++point_i)
64 {
65 pcl::Indices k_indices (16);
66 std::vector<float> k_distances (16);
67 kdtree->nearestKSearch (static_cast<int> (point_i), 16, k_indices, k_distances);
68
69 for (std::size_t k_i = 0; k_i < k_indices.size (); ++k_i)
70 add_edge (point_i, k_indices[k_i], Weight (std::sqrt (k_distances[k_i])), cloud_graph);
71 }
72
73 const std::size_t E = num_edges (cloud_graph),
74 V = num_vertices (cloud_graph);
75 PCL_INFO ("The graph has %lu vertices and %lu edges.\n", V, E);
76 geodesic_distances_.clear ();
77 for (std::size_t i = 0; i < V; ++i)
78 {
79 std::vector<float> aux (V);
80 geodesic_distances_.push_back (aux);
81 }
82 johnson_all_pairs_shortest_paths (cloud_graph, geodesic_distances_);
83
84 PCL_INFO ("Done generating the graph\n");
85}
86
87
88//////////////////////////////////////////////////////////////////////////////////////////////
89template <typename PointT> bool
91{
93 {
94 PCL_ERROR ("[pcl::StatisticalMultiscaleInterestRegionExtraction::initCompute] PCLBase::initCompute () failed - no input cloud was given.\n");
95 return (false);
96 }
97 if (scale_values_.empty ())
98 {
99 PCL_ERROR ("[pcl::StatisticalMultiscaleInterestRegionExtraction::initCompute] No scale values were given\n");
100 return (false);
101 }
102
103 return (true);
104}
105
106
107//////////////////////////////////////////////////////////////////////////////////////////////
108template <typename PointT> void
110 float &radius,
111 std::vector<int> &result_indices)
112{
113 for (std::size_t i = 0; i < geodesic_distances_[query_index].size (); ++i)
114 if (i != query_index && geodesic_distances_[query_index][i] < radius)
115 result_indices.push_back (static_cast<int> (i));
116}
117
118
119//////////////////////////////////////////////////////////////////////////////////////////////
120template <typename PointT> void
122{
123 if (!initCompute ())
124 {
125 PCL_ERROR ("StatisticalMultiscaleInterestRegionExtraction: not completely initialized\n");
126 return;
127 }
128
129 generateCloudGraph ();
130
131 computeF ();
132
133 extractExtrema (rois);
134}
135
136
137//////////////////////////////////////////////////////////////////////////////////////////////
138template <typename PointT> void
140{
141 PCL_INFO ("Calculating statistical information\n");
142
143 // declare and initialize data structure
144 F_scales_.resize (scale_values_.size ());
145 std::vector<float> point_density (input_->size ()),
146 F (input_->size ());
147 std::vector<std::vector<float> > phi (input_->size ());
148 std::vector<float> phi_row (input_->size ());
149
150 for (std::size_t scale_i = 0; scale_i < scale_values_.size (); ++scale_i)
151 {
152 float scale_squared = scale_values_[scale_i] * scale_values_[scale_i];
153
154 // calculate point density for each point x_i
155 for (std::size_t point_i = 0; point_i < input_->size (); ++point_i)
156 {
157 float point_density_i = 0.0;
158 for (std::size_t point_j = 0; point_j < input_->size (); ++point_j)
159 {
160 float d_g = geodesic_distances_[point_i][point_j];
161 float phi_i_j = 1.0f / std::sqrt (2.0f * static_cast<float> (M_PI) * scale_squared) * std::exp ( (-1) * d_g*d_g / (2.0f * scale_squared));
162
163 point_density_i += phi_i_j;
164 phi_row[point_j] = phi_i_j;
165 }
166 point_density[point_i] = point_density_i;
167 phi[point_i] = phi_row;
168 }
169
170 // compute weights for each pair (x_i, x_j), evaluate the operator A_hat
171 for (std::size_t point_i = 0; point_i < input_->size (); ++point_i)
172 {
173 float A_hat_normalization = 0.0;
174 PointT A_hat; A_hat.x = A_hat.y = A_hat.z = 0.0;
175 for (std::size_t point_j = 0; point_j < input_->size (); ++point_j)
176 {
177 float phi_hat_i_j = phi[point_i][point_j] / (point_density[point_i] * point_density[point_j]);
178 A_hat_normalization += phi_hat_i_j;
179
180 PointT aux = (*input_)[point_j];
181 aux.x *= phi_hat_i_j; aux.y *= phi_hat_i_j; aux.z *= phi_hat_i_j;
182
183 A_hat.x += aux.x; A_hat.y += aux.y; A_hat.z += aux.z;
184 }
185 A_hat.x /= A_hat_normalization; A_hat.y /= A_hat_normalization; A_hat.z /= A_hat_normalization;
186
187 // compute the invariant F
188 float aux = 2.0f / scale_values_[scale_i] * euclideanDistance<PointT, PointT> (A_hat, (*input_)[point_i]);
189 F[point_i] = aux * std::exp (-aux);
190 }
191
192 F_scales_[scale_i] = F;
193 }
194}
195
196
197//////////////////////////////////////////////////////////////////////////////////////////////
198template <typename PointT> void
200{
201 std::vector<std::vector<bool> > is_min (scale_values_.size ()),
202 is_max (scale_values_.size ());
203
204 // for each point, check if it is a local extrema on each scale
205 for (std::size_t scale_i = 0; scale_i < scale_values_.size (); ++scale_i)
206 {
207 std::vector<bool> is_min_scale (input_->size ()),
208 is_max_scale (input_->size ());
209 for (std::size_t point_i = 0; point_i < input_->size (); ++point_i)
210 {
211 std::vector<int> nn_indices;
212 geodesicFixedRadiusSearch (point_i, scale_values_[scale_i], nn_indices);
213 bool is_max_point = true, is_min_point = true;
214 for (const auto &nn_index : nn_indices)
215 if (F_scales_[scale_i][point_i] < F_scales_[scale_i][nn_index])
216 is_max_point = false;
217 else
218 is_min_point = false;
219
220 is_min_scale[point_i] = is_min_point;
221 is_max_scale[point_i] = is_max_point;
222 }
223
224 is_min[scale_i] = is_min_scale;
225 is_max[scale_i] = is_max_scale;
226 }
227
228 // look for points that are min/max over three consecutive scales
229 for (std::size_t scale_i = 1; scale_i < scale_values_.size () - 1; ++scale_i)
230 {
231 for (std::size_t point_i = 0; point_i < input_->size (); ++point_i)
232 if ((is_min[scale_i - 1][point_i] && is_min[scale_i][point_i] && is_min[scale_i + 1][point_i]) ||
233 (is_max[scale_i - 1][point_i] && is_max[scale_i][point_i] && is_max[scale_i + 1][point_i]))
234 {
235 // add the point to the result vector
236 IndicesPtr region (new pcl::Indices);
237 region->push_back (static_cast<int> (point_i));
238
239 // and also add its scale-sized geodesic neighborhood
240 std::vector<int> nn_indices;
241 geodesicFixedRadiusSearch (point_i, scale_values_[scale_i], nn_indices);
242 region->insert (region->end (), nn_indices.begin (), nn_indices.end ());
243 rois.push_back (region);
244 }
245 }
246}
247
248
249#define PCL_INSTANTIATE_StatisticalMultiscaleInterestRegionExtraction(T) template class PCL_EXPORTS pcl::StatisticalMultiscaleInterestRegionExtraction<T>;
250
251#endif /* PCL_FEATURES_IMPL_STATISTICAL_MULTISCALE_INTEREST_REGION_EXTRACTION_H_ */
252
PCL base class.
Definition pcl_base.h:70
Class for extracting interest regions from unstructured point clouds, based on a multi scale statisti...
void computeRegionsOfInterest(std::list< IndicesPtr > &rois)
The method to be called in order to run the algorithm and produce the resulting set of regions of int...
void generateCloudGraph()
Method that generates the underlying nearest neighbor graph based on the input point cloud.
shared_ptr< pcl::search::Search< PointT > > Ptr
Definition search.h:81
virtual int nearestKSearch(const PointT &point, int k, Indices &k_indices, std::vector< float > &k_sqr_distances) const =0
Search for the k-nearest neighbors for the given query point.
Define standard C methods to do distance calculations.
@ many_knn_search
The search method will mainly be used for nearestKSearch where k is larger than 1.
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition types.h:133
shared_ptr< Indices > IndicesPtr
Definition pcl_base.h:58
#define M_PI
Definition pcl_macros.h:201
A point structure representing Euclidean xyz coordinates, and the RGB color.