38 #ifndef PCL_FEATURES_IMPL_STATISTICAL_MULTISCALE_INTEREST_REGION_EXTRACTION_H_
39 #define PCL_FEATURES_IMPL_STATISTICAL_MULTISCALE_INTEREST_REGION_EXTRACTION_H_
43 #include <boost/graph/adjacency_list.hpp>
44 #include <boost/property_map/property_map.hpp>
45 #include <boost/graph/johnson_all_pairs_shortest.hpp>
49 template <
typename Po
intT>
void
56 using namespace boost;
57 typedef property<edge_weight_t, float> Weight;
58 typedef adjacency_list<vecS, vecS, undirectedS, no_property, Weight> Graph;
61 for (
size_t point_i = 0; point_i < input_->points.size (); ++point_i)
63 std::vector<int> k_indices (16);
64 std::vector<float> k_distances (16);
65 kdtree.
nearestKSearch (static_cast<int> (point_i), 16, k_indices, k_distances);
67 for (
int k_i = 0; k_i < static_cast<int> (k_indices.size ()); ++k_i)
68 add_edge (point_i, k_indices[k_i], Weight (sqrtf (k_distances[k_i])), cloud_graph);
71 const size_t E = num_edges (cloud_graph),
72 V = num_vertices (cloud_graph);
73 PCL_INFO (
"The graph has %lu vertices and %lu edges.\n", V, E);
74 geodesic_distances_.clear ();
75 for (
size_t i = 0; i < V; ++i)
77 std::vector<float> aux (V);
78 geodesic_distances_.push_back (aux);
80 johnson_all_pairs_shortest_paths (cloud_graph, geodesic_distances_);
82 PCL_INFO (
"Done generating the graph\n");
87 template <
typename Po
intT>
bool
92 PCL_ERROR (
"[pcl::StatisticalMultiscaleInterestRegionExtraction::initCompute] PCLBase::initCompute () failed - no input cloud was given.\n");
95 if (scale_values_.empty ())
97 PCL_ERROR (
"[pcl::StatisticalMultiscaleInterestRegionExtraction::initCompute] No scale values were given\n");
106 template <
typename Po
intT>
void
109 std::vector<int> &result_indices)
111 for (
size_t i = 0; i < geodesic_distances_[query_index].size (); ++i)
112 if (i != query_index && geodesic_distances_[query_index][i] < radius)
113 result_indices.push_back (static_cast<int> (i));
118 template <
typename Po
intT>
void
123 PCL_ERROR (
"StatisticalMultiscaleInterestRegionExtraction: not completely initialized\n");
127 generateCloudGraph ();
131 extractExtrema (rois);
136 template <
typename Po
intT>
void
139 PCL_INFO (
"Calculating statistical information\n");
142 F_scales_.resize (scale_values_.size ());
143 std::vector<float> point_density (input_->points.size ()),
144 F (input_->points.size ());
145 std::vector<std::vector<float> > phi (input_->points.size ());
146 std::vector<float> phi_row (input_->points.size ());
148 for (
size_t scale_i = 0; scale_i < scale_values_.size (); ++scale_i)
150 float scale_squared = scale_values_[scale_i] * scale_values_[scale_i];
153 for (
size_t point_i = 0; point_i < input_->points.size (); ++point_i)
155 float point_density_i = 0.0;
156 for (
size_t point_j = 0; point_j < input_->points.size (); ++point_j)
158 float d_g = geodesic_distances_[point_i][point_j];
159 float phi_i_j = 1.0f / sqrtf (2.0f * static_cast<float> (M_PI) * scale_squared) * expf ( (-1) * d_g*d_g / (2.0f * scale_squared));
161 point_density_i += phi_i_j;
162 phi_row[point_j] = phi_i_j;
164 point_density[point_i] = point_density_i;
165 phi[point_i] = phi_row;
169 for (
size_t point_i = 0; point_i < input_->points.size (); ++point_i)
171 float A_hat_normalization = 0.0;
172 PointT A_hat; A_hat.x = A_hat.y = A_hat.z = 0.0;
173 for (
size_t point_j = 0; point_j < input_->points.size (); ++point_j)
175 float phi_hat_i_j = phi[point_i][point_j] / (point_density[point_i] * point_density[point_j]);
176 A_hat_normalization += phi_hat_i_j;
178 PointT aux = input_->points[point_j];
179 aux.x *= phi_hat_i_j; aux.y *= phi_hat_i_j; aux.z *= phi_hat_i_j;
181 A_hat.x += aux.x; A_hat.y += aux.y; A_hat.z += aux.z;
183 A_hat.x /= A_hat_normalization; A_hat.y /= A_hat_normalization; A_hat.z /= A_hat_normalization;
186 float aux = 2.0f / scale_values_[scale_i] * euclideanDistance<PointT, PointT> (A_hat, input_->points[point_i]);
187 F[point_i] = aux * expf (-aux);
190 F_scales_[scale_i] = F;
196 template <
typename Po
intT>
void
199 std::vector<std::vector<bool> > is_min (scale_values_.size ()),
200 is_max (scale_values_.size ());
203 for (
size_t scale_i = 0; scale_i < scale_values_.size (); ++scale_i)
205 std::vector<bool> is_min_scale (input_->points.size ()),
206 is_max_scale (input_->points.size ());
207 for (
size_t point_i = 0; point_i < input_->points.size (); ++point_i)
209 std::vector<int> nn_indices;
210 geodesicFixedRadiusSearch (point_i, scale_values_[scale_i], nn_indices);
211 bool is_max_point =
true, is_min_point =
true;
212 for (std::vector<int>::iterator nn_it = nn_indices.begin (); nn_it != nn_indices.end (); ++nn_it)
213 if (F_scales_[scale_i][point_i] < F_scales_[scale_i][*nn_it])
214 is_max_point =
false;
216 is_min_point =
false;
218 is_min_scale[point_i] = is_min_point;
219 is_max_scale[point_i] = is_max_point;
222 is_min[scale_i] = is_min_scale;
223 is_max[scale_i] = is_max_scale;
227 for (
size_t scale_i = 1; scale_i < scale_values_.size () - 1; ++scale_i)
229 for (
size_t point_i = 0; point_i < input_->points.size (); ++point_i)
230 if ((is_min[scale_i - 1][point_i] && is_min[scale_i][point_i] && is_min[scale_i + 1][point_i]) ||
231 (is_max[scale_i - 1][point_i] && is_max[scale_i][point_i] && is_max[scale_i + 1][point_i]))
235 region->push_back (static_cast<int> (point_i));
238 std::vector<int> nn_indices;
239 geodesicFixedRadiusSearch (point_i, scale_values_[scale_i], nn_indices);
240 region->insert (region->end (), nn_indices.begin (), nn_indices.end ());
241 rois.push_back (region);
247 #define PCL_INSTANTIATE_StatisticalMultiscaleInterestRegionExtraction(T) template class PCL_EXPORTS pcl::StatisticalMultiscaleInterestRegionExtraction<T>;