42 #ifndef PCL_REGISTRATION_IMPL_PYRAMID_FEATURE_MATCHING_H_
43 #define PCL_REGISTRATION_IMPL_PYRAMID_FEATURE_MATCHING_H_
45 #include <pcl/console/print.h>
50 template <
typename Po
intFeature>
57 if (pyramid_a->nr_dimensions != pyramid_b->nr_dimensions) {
58 PCL_ERROR(
"[pcl::PyramidFeatureMatching::comparePyramidFeatureHistograms] The two "
59 "given pyramids have different numbers of dimensions: %u vs %u\n",
60 pyramid_a->nr_dimensions,
61 pyramid_b->nr_dimensions);
64 if (pyramid_a->nr_levels != pyramid_b->nr_levels) {
65 PCL_ERROR(
"[pcl::PyramidFeatureMatching::comparePyramidFeatureHistograms] The two "
66 "given pyramids have different numbers of levels: %u vs %u\n",
68 pyramid_b->nr_levels);
73 if (pyramid_a->hist_levels[0].hist.size() != pyramid_b->hist_levels[0].hist.size()) {
74 PCL_ERROR(
"[pcl::PyramidFeatureMatching::comparePyramidFeatureHistograms] The two "
75 "given pyramids have different numbers of bins on level 0: %u vs %u\n",
76 pyramid_a->hist_levels[0].hist.size(),
77 pyramid_b->hist_levels[0].hist.size());
80 float match_count_level = 0.0f;
81 for (std::size_t bin_i = 0; bin_i < pyramid_a->hist_levels[0].hist.size(); ++bin_i) {
82 if (pyramid_a->hist_levels[0].hist[bin_i] < pyramid_b->hist_levels[0].hist[bin_i])
83 match_count_level +=
static_cast<float>(pyramid_a->hist_levels[0].hist[bin_i]);
85 match_count_level +=
static_cast<float>(pyramid_b->hist_levels[0].hist[bin_i]);
88 float match_count = match_count_level;
89 for (std::size_t level_i = 1; level_i < pyramid_a->nr_levels; ++level_i) {
90 if (pyramid_a->hist_levels[level_i].hist.size() !=
91 pyramid_b->hist_levels[level_i].hist.size()) {
93 "[pcl::PyramidFeatureMatching::comparePyramidFeatureHistograms] The two "
94 "given pyramids have different numbers of bins on level %u: %u vs %u\n",
96 pyramid_a->hist_levels[level_i].hist.size(),
97 pyramid_b->hist_levels[level_i].hist.size());
101 float match_count_prev_level = match_count_level;
102 match_count_level = 0.0f;
103 for (std::size_t bin_i = 0; bin_i < pyramid_a->hist_levels[level_i].hist.size();
105 if (pyramid_a->hist_levels[level_i].hist[bin_i] <
106 pyramid_b->hist_levels[level_i].hist[bin_i])
108 static_cast<float>(pyramid_a->hist_levels[level_i].hist[bin_i]);
111 static_cast<float>(pyramid_b->hist_levels[level_i].hist[bin_i]);
114 float level_normalization_factor = powf(2.0f,
static_cast<float>(level_i));
116 (match_count_level - match_count_prev_level) / level_normalization_factor;
120 float self_similarity_a =
static_cast<float>(pyramid_a->nr_features),
121 self_similarity_b =
static_cast<float>(pyramid_b->nr_features);
122 PCL_DEBUG(
"[pcl::PyramidFeatureMatching::comparePyramidFeatureHistograms] Self "
123 "similarity measures: %f, %f\n",
126 match_count /= std::sqrt(self_similarity_a * self_similarity_b);
131 template <
typename Po
intFeature>
137 , is_computed_(false)
141 template <
typename Po
intFeature>
144 PointFeature>::PyramidFeatureHistogramLevel::initializeHistogramLevel()
146 std::size_t total_vector_size = 1;
147 for (std::vector<std::size_t>::iterator dim_it = bins_per_dimension.begin();
148 dim_it != bins_per_dimension.end();
150 total_vector_size *= *dim_it;
152 hist.resize(total_vector_size, 0);
155 template <
typename Po
intFeature>
157 PyramidFeatureHistogram<PointFeature>::initializeHistogram()
161 PCL_ERROR(
"[pcl::PyramidFeatureHistogram::initializeHistogram] PCLBase initCompute "
166 if (dimension_range_input_.empty()) {
167 PCL_ERROR(
"[pcl::PyramidFeatureHistogram::initializeHistogram] Input dimension "
168 "range was not set\n");
172 if (dimension_range_target_.empty()) {
173 PCL_ERROR(
"[pcl::PyramidFeatureHistogram::initializeHistogram] Target dimension "
174 "range was not set\n");
178 if (dimension_range_input_.size() != dimension_range_target_.size()) {
179 PCL_ERROR(
"[pcl::PyramidFeatureHistogram::initializeHistogram] Input and target "
180 "dimension ranges do not agree in size: %u vs %u\n",
181 dimension_range_input_.size(),
182 dimension_range_target_.size());
186 nr_dimensions = dimension_range_target_.size();
187 nr_features = input_->size();
189 for (std::vector<std::pair<float, float>>::iterator range_it =
190 dimension_range_target_.begin();
191 range_it != dimension_range_target_.end();
193 float aux = range_it->first - range_it->second;
197 nr_levels =
static_cast<std::size_t
>(std::ceil(std::log2(D)));
198 PCL_DEBUG(
"[pcl::PyramidFeatureHistogram::initializeHistogram] Pyramid will have %u "
199 "levels with a hyper-parallelepiped diagonal size of %f\n",
203 hist_levels.resize(nr_levels);
204 for (std::size_t level_i = 0; level_i < nr_levels; ++level_i) {
205 std::vector<std::size_t> bins_per_dimension(nr_dimensions);
206 std::vector<float> bin_step(nr_dimensions);
207 for (std::size_t dim_i = 0; dim_i < nr_dimensions; ++dim_i) {
208 bins_per_dimension[dim_i] =
static_cast<std::size_t
>(
209 std::ceil((dimension_range_target_[dim_i].second -
210 dimension_range_target_[dim_i].first) /
211 (powf(2.0f,
static_cast<float>(level_i)) *
212 std::sqrt(
static_cast<float>(nr_dimensions)))));
213 bin_step[dim_i] = powf(2.0f,
static_cast<float>(level_i)) *
214 std::sqrt(
static_cast<float>(nr_dimensions));
216 hist_levels[level_i] = PyramidFeatureHistogramLevel(bins_per_dimension, bin_step);
218 PCL_DEBUG(
"[pcl::PyramidFeatureHistogram::initializeHistogram] Created vector of "
219 "size %u at level %u\nwith #bins per dimension:",
220 hist_levels.back().hist.size(),
222 for (std::size_t dim_i = 0; dim_i < nr_dimensions; ++dim_i)
223 PCL_DEBUG(
"%u ", bins_per_dimension[dim_i]);
230 template <
typename Po
intFeature>
232 PyramidFeatureHistogram<PointFeature>::at(std::vector<std::size_t>& access,
235 if (access.size() != nr_dimensions) {
237 "[pcl::PyramidFeatureHistogram::at] Cannot access histogram position because "
238 "the access point does not have the right number of dimensions\n");
239 return hist_levels.front().hist.front();
241 if (level >= hist_levels.size()) {
243 "[pcl::PyramidFeatureHistogram::at] Trying to access a too large level\n");
244 return hist_levels.front().hist.front();
247 std::size_t vector_position = 0;
248 std::size_t dim_accumulator = 1;
250 for (
int i =
static_cast<int>(access.size()) - 1; i >= 0; --i) {
251 vector_position += access[i] * dim_accumulator;
252 dim_accumulator *= hist_levels[level].bins_per_dimension[i];
255 return hist_levels[level].hist[vector_position];
258 template <
typename Po
intFeature>
260 PyramidFeatureHistogram<PointFeature>::at(std::vector<float>& feature,
263 if (feature.size() != nr_dimensions) {
264 PCL_ERROR(
"[pcl::PyramidFeatureHistogram::at] The given feature vector does not "
265 "match the feature dimensions of the pyramid histogram: %u vs %u\n",
268 return hist_levels.front().hist.front();
270 if (level >= hist_levels.size()) {
272 "[pcl::PyramidFeatureHistogram::at] Trying to access a too large level\n");
273 return hist_levels.front().hist.front();
276 std::vector<std::size_t> access;
277 for (std::size_t dim_i = 0; dim_i < nr_dimensions; ++dim_i)
278 access.push_back(
static_cast<std::size_t
>(
279 std::floor((feature[dim_i] - dimension_range_target_[dim_i].first) /
280 hist_levels[level].bin_step[dim_i])));
282 return at(access, level);
285 template <
typename Po
intFeature>
287 PyramidFeatureHistogram<PointFeature>::convertFeatureToVector(
288 const PointFeature& feature, std::vector<float>& feature_vector)
291 feature_vector.resize(feature_representation_->getNumberOfDimensions());
292 feature_representation_->vectorize(feature, feature_vector);
295 for (std::size_t i = 0; i < feature_vector.size(); ++i)
297 (feature_vector[i] - dimension_range_input_[i].first) /
298 (dimension_range_input_[i].second - dimension_range_input_[i].first) *
299 (dimension_range_target_[i].second - dimension_range_target_[i].first) +
300 dimension_range_target_[i].first;
303 template <
typename Po
intFeature>
307 if (!initializeHistogram())
310 for (
const auto& point : *input_) {
311 std::vector<float> feature_vector;
312 convertFeatureToVector(point, feature_vector);
313 addFeature(feature_vector);
319 template <
typename Po
intFeature>
323 for (std::size_t level_i = 0; level_i < nr_levels; ++level_i)
324 at(feature, level_i)++;
329 #define PCL_INSTANTIATE_PyramidFeatureHistogram(PointFeature) \
330 template class PCL_EXPORTS pcl::PyramidFeatureHistogram<PointFeature>;