40 #include <pcl/recognition/quantizable_modality.h>
41 #include <pcl/recognition/distance_map.h>
43 #include <pcl/pcl_base.h>
44 #include <pcl/point_cloud.h>
46 #include <pcl/recognition/point_types.h>
58 template <
typename Po
intInT>
91 return (filtered_quantized_colors_);
97 return (spreaded_filtered_quantized_colors_);
102 std::vector<QuantizedMultiModFeature> & features)
const;
133 float feature_distance_threshold_;
144 template <
typename Po
intInT>
146 : feature_distance_threshold_ (1.0f), quantized_colors_ (), filtered_quantized_colors_ (), spreaded_filtered_quantized_colors_ ()
151 template <
typename Po
intInT>
159 filterQuantizedColors ();
163 const int spreading_size = 8;
165 spreaded_filtered_quantized_colors_, spreading_size);
169 template <
typename Po
intInT>
171 const std::size_t nr_features,
172 const std::size_t modality_index,
173 std::vector<QuantizedMultiModFeature> & features)
const
175 const std::size_t width = mask.
getWidth ();
176 const std::size_t height = mask.
getHeight ();
179 for (std::size_t map_index = 0; map_index < 8; ++map_index)
180 mask_maps[map_index].resize (width, height);
182 unsigned char map[255]{};
196 for (std::size_t row_index = 0; row_index < height; ++row_index)
198 for (std::size_t col_index = 0; col_index < width; ++col_index)
200 if (mask (col_index, row_index) != 0)
203 const unsigned char quantized_value = filtered_quantized_colors_ (col_index, row_index);
205 if (quantized_value == 0)
207 const int dist_map_index = map[quantized_value];
209 distance_map_indices (col_index, row_index) = dist_map_index;
211 mask_maps[dist_map_index] (col_index, row_index) = 255;
217 for (
int map_index = 0; map_index < 8; ++map_index)
218 computeDistanceMap (mask_maps[map_index], distance_maps[map_index]);
220 std::list<Candidate> list1;
221 std::list<Candidate> list2;
223 float weights[8] = {0,0,0,0,0,0,0,0};
225 const std::size_t off = 4;
226 for (std::size_t row_index = off; row_index < height-off; ++row_index)
228 for (std::size_t col_index = off; col_index < width-off; ++col_index)
230 if (mask (col_index, row_index) != 0)
233 const unsigned char quantized_value = filtered_quantized_colors_ (col_index, row_index);
239 if (quantized_value != 0)
241 const int distance_map_index = map[quantized_value];
244 const float distance = distance_maps[distance_map_index] (col_index, row_index);
246 if (
distance >= feature_distance_threshold_)
251 candidate.
x = col_index;
252 candidate.
y = row_index;
253 candidate.
bin_index = distance_map_index;
255 list1.push_back (candidate);
257 ++weights[distance_map_index];
264 for (
typename std::list<Candidate>::iterator iter = list1.begin (); iter != list1.end (); ++iter)
265 iter->distance *= 1.0f / weights[iter->bin_index];
269 if (list1.size () <= nr_features)
271 features.reserve (list1.size ());
272 for (
typename std::list<Candidate>::iterator iter = list1.begin (); iter != list1.end (); ++iter)
276 feature.
x =
static_cast<int> (iter->x);
277 feature.
y =
static_cast<int> (iter->y);
279 feature.
quantized_value = filtered_quantized_colors_ (iter->x, iter->y);
281 features.push_back (feature);
287 int distance =
static_cast<int> (list1.size () / nr_features + 1);
288 while (list2.size () != nr_features)
291 for (
typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
293 bool candidate_accepted =
true;
295 for (
typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
297 const int dx =
static_cast<int> (iter1->x) -
static_cast<int> (iter2->x);
298 const int dy =
static_cast<int> (iter1->y) -
static_cast<int> (iter2->y);
299 const int tmp_distance = dx*dx + dy*dy;
301 if (tmp_distance < sqr_distance)
303 candidate_accepted =
false;
308 if (candidate_accepted)
309 list2.push_back (*iter1);
311 if (list2.size () == nr_features)
break;
316 for (
typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
320 feature.
x =
static_cast<int> (iter2->x);
321 feature.
y =
static_cast<int> (iter2->y);
323 feature.
quantized_value = filtered_quantized_colors_ (iter2->x, iter2->y);
325 features.push_back (feature);
330 template <
typename Po
intInT>
334 const std::size_t width = input_->width;
335 const std::size_t height = input_->height;
337 quantized_colors_.resize (width, height);
339 for (std::size_t row_index = 0; row_index < height; ++row_index)
341 for (std::size_t col_index = 0; col_index < width; ++col_index)
343 const float r =
static_cast<float> ((*input_) (col_index, row_index).r);
344 const float g =
static_cast<float> ((*input_) (col_index, row_index).g);
345 const float b =
static_cast<float> ((*input_) (col_index, row_index).b);
347 quantized_colors_ (col_index, row_index) = quantizeColorOnRGBExtrema (r, g, b);
353 template <
typename Po
intInT>
357 const std::size_t width = input_->width;
358 const std::size_t height = input_->height;
360 filtered_quantized_colors_.resize (width, height);
363 for (std::size_t row_index = 1; row_index < height-1; ++row_index)
365 for (std::size_t col_index = 1; col_index < width-1; ++col_index)
367 unsigned char histogram[8] = {0,0,0,0,0,0,0,0};
370 const unsigned char * data_ptr = quantized_colors_.getData () + (row_index-1)*width+col_index-1;
371 assert (0 <= data_ptr[0] && data_ptr[0] < 9 &&
372 0 <= data_ptr[1] && data_ptr[1] < 9 &&
373 0 <= data_ptr[2] && data_ptr[2] < 9);
374 ++histogram[data_ptr[0]];
375 ++histogram[data_ptr[1]];
376 ++histogram[data_ptr[2]];
379 const unsigned char * data_ptr = quantized_colors_.getData () + row_index*width+col_index-1;
380 assert (0 <= data_ptr[0] && data_ptr[0] < 9 &&
381 0 <= data_ptr[1] && data_ptr[1] < 9 &&
382 0 <= data_ptr[2] && data_ptr[2] < 9);
383 ++histogram[data_ptr[0]];
384 ++histogram[data_ptr[1]];
385 ++histogram[data_ptr[2]];
388 const unsigned char * data_ptr = quantized_colors_.getData () + (row_index+1)*width+col_index-1;
389 assert (0 <= data_ptr[0] && data_ptr[0] < 9 &&
390 0 <= data_ptr[1] && data_ptr[1] < 9 &&
391 0 <= data_ptr[2] && data_ptr[2] < 9);
392 ++histogram[data_ptr[0]];
393 ++histogram[data_ptr[1]];
394 ++histogram[data_ptr[2]];
397 unsigned char max_hist_value = 0;
398 int max_hist_index = -1;
409 if (max_hist_value < histogram[0]) {max_hist_index = 0; max_hist_value = histogram[0];}
410 if (max_hist_value < histogram[1]) {max_hist_index = 1; max_hist_value = histogram[1];}
411 if (max_hist_value < histogram[2]) {max_hist_index = 2; max_hist_value = histogram[2];}
412 if (max_hist_value < histogram[3]) {max_hist_index = 3; max_hist_value = histogram[3];}
413 if (max_hist_value < histogram[4]) {max_hist_index = 4; max_hist_value = histogram[4];}
414 if (max_hist_value < histogram[5]) {max_hist_index = 5; max_hist_value = histogram[5];}
415 if (max_hist_value < histogram[6]) {max_hist_index = 6; max_hist_value = histogram[6];}
416 if (max_hist_value < histogram[7]) {max_hist_index = 7; max_hist_value = histogram[7];}
419 filtered_quantized_colors_ (col_index, row_index) = 0x1 << max_hist_index;
428 template <
typename Po
intInT>
434 const float r_inv = 255.0f-r;
435 const float g_inv = 255.0f-g;
436 const float b_inv = 255.0f-b;
438 const float dist_0 = (r*r + g*g + b*b)*2.0f;
439 const float dist_1 = r*r + g*g + b_inv*b_inv;
440 const float dist_2 = r*r + g_inv*g_inv+ b*b;
441 const float dist_3 = r*r + g_inv*g_inv + b_inv*b_inv;
442 const float dist_4 = r_inv*r_inv + g*g + b*b;
443 const float dist_5 = r_inv*r_inv + g*g + b_inv*b_inv;
444 const float dist_6 = r_inv*r_inv + g_inv*g_inv+ b*b;
445 const float dist_7 = (r_inv*r_inv + g_inv*g_inv + b_inv*b_inv)*1.5f;
447 const float min_dist = std::min (std::min (std::min (dist_0, dist_1), std::min (dist_2, dist_3)), std::min (std::min (dist_4, dist_5), std::min (dist_6, dist_7)));
449 if (min_dist == dist_0)
453 if (min_dist == dist_1)
457 if (min_dist == dist_2)
461 if (min_dist == dist_3)
465 if (min_dist == dist_4)
469 if (min_dist == dist_5)
473 if (min_dist == dist_6)
481 template <
typename Po
intInT>
void
485 const std::size_t width = input.
getWidth ();
486 const std::size_t height = input.
getHeight ();
488 output.
resize (width, height);
492 const unsigned char * mask_map = input.
getData ();
493 float * distance_map = output.
getData ();
494 for (std::size_t index = 0; index < width*height; ++index)
496 if (mask_map[index] == 0)
497 distance_map[index] = 0.0f;
499 distance_map[index] =
static_cast<float> (width + height);
503 float * previous_row = distance_map;
504 float * current_row = previous_row + width;
505 for (std::size_t ri = 1; ri < height; ++ri)
507 for (std::size_t ci = 1; ci < width; ++ci)
509 const float up_left = previous_row [ci - 1] + 1.4f;
510 const float up = previous_row [ci] + 1.0f;
511 const float up_right = previous_row [ci + 1] + 1.4f;
512 const float left = current_row [ci - 1] + 1.0f;
513 const float center = current_row [ci];
515 const float min_value = std::min (std::min (up_left, up), std::min (left, up_right));
517 if (min_value < center)
518 current_row[ci] = min_value;
520 previous_row = current_row;
521 current_row += width;
525 float * next_row = distance_map + width * (height - 1);
526 current_row = next_row - width;
527 for (
int ri =
static_cast<int> (height)-2; ri >= 0; --ri)
529 for (
int ci =
static_cast<int> (width)-2; ci >= 0; --ci)
531 const float lower_left = next_row [ci - 1] + 1.4f;
532 const float lower = next_row [ci] + 1.0f;
533 const float lower_right = next_row [ci + 1] + 1.4f;
534 const float right = current_row [ci + 1] + 1.0f;
535 const float center = current_row [ci];
537 const float min_value = std::min (std::min (lower_left, lower), std::min (right, lower_right));
539 if (min_value < center)
540 current_row[ci] = min_value;
542 next_row = current_row;
543 current_row -= width;
void computeDistanceMap(const MaskMap &input, DistanceMap &output) const
virtual void setInputCloud(const typename PointCloudIn::ConstPtr &cloud)
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method)
void filterQuantizedColors()
QuantizedMap & getSpreadedQuantizedMap()
Returns a reference to the internally computed spread quantized map.
virtual ~ColorModality()=default
static int quantizeColorOnRGBExtrema(const float r, const float g, const float b)
QuantizedMap & getQuantizedMap()
Returns a reference to the internally computed quantized map.
virtual void processInputData()
void extractFeatures(const MaskMap &mask, std::size_t nr_features, std::size_t modalityIndex, std::vector< QuantizedMultiModFeature > &features) const
Extracts features from this modality within the specified mask.
Represents a distance map obtained from a distance transformation.
float * getData()
Returns a pointer to the beginning of map.
void resize(const std::size_t width, const std::size_t height)
Resizes the map to the specified size.
std::size_t getWidth() const
unsigned char * getData()
std::size_t getHeight() const
PointCloudConstPtr input_
The input point cloud dataset.
shared_ptr< const PointCloud< PointInT > > ConstPtr
Interface for a quantizable modality.
static void spreadQuantizedMap(const QuantizedMap &input_map, QuantizedMap &output_map, std::size_t spreading_size)
Defines all the PCL implemented PointT point type structures.
float distance(const PointT &p1, const PointT &p2)
bool operator<(const Candidate &rhs)
Feature that defines a position and quantized value in a specific modality.
std::size_t modality_index
the index of the corresponding modality.
unsigned char quantized_value
the quantized value attached to the feature.