40 #include <pcl/recognition/quantizable_modality.h>
42 #include <pcl/pcl_base.h>
43 #include <pcl/point_cloud.h>
44 #include <pcl/point_types.h>
45 #include <pcl/recognition/point_types.h>
46 #include <pcl/filters/convolution.h>
56 template <
typename Po
intInT>
106 gradient_magnitude_threshold_ = threshold;
116 gradient_magnitude_threshold_feature_extraction_ = threshold;
125 feature_selection_method_ = method;
132 spreading_size_ = spreading_size;
141 variable_feature_nr_ = enabled;
148 return (filtered_quantized_color_gradients_);
155 return (spreaded_filtered_quantized_color_gradients_);
162 return (color_gradients_);
174 std::vector<QuantizedMultiModFeature> & features)
const override;
184 std::vector<QuantizedMultiModFeature> & features)
const override;
211 computeGaussianKernel (
const std::size_t kernel_size,
const float sigma, std::vector <float> & kernel_values);
243 bool variable_feature_nr_{
false};
252 float gradient_magnitude_threshold_{10.0f};
254 float gradient_magnitude_threshold_feature_extraction_{55.0f};
260 std::size_t spreading_size_{8};
274 template <
typename Po
intInT>
278 , feature_selection_method_ (DISTANCE_MAGNITUDE_SCORE)
283 template <
typename Po
intInT>
288 template <
typename Po
intInT>
void
293 const int n =
static_cast<int>(kernel_size);
294 constexpr
int SMALL_GAUSSIAN_SIZE = 7;
295 static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
298 {0.25f, 0.5f, 0.25f},
299 {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
300 {0.03125f, 0.109375f, 0.21875f, 0.28125f, 0.21875f, 0.109375f, 0.03125f}
303 const float* fixed_kernel = n % 2 == 1 && n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ?
304 small_gaussian_tab[n>>1] :
nullptr;
308 kernel_values.resize (n);
309 float* cf = kernel_values.data();
312 double sigmaX = sigma > 0 ? sigma : ((n-1)*0.5 - 1)*0.3 + 0.8;
313 double scale2X = -0.5/(sigmaX*sigmaX);
316 for(
int i = 0; i < n; i++ )
318 double x = i - (n-1)*0.5;
319 double t = fixed_kernel ?
static_cast<double>(fixed_kernel[i]) : std::exp (scale2X*x*x);
321 cf[i] =
static_cast<float>(t);
326 for (
int i = 0; i < n; i++ )
328 cf[i] =
static_cast<float>(cf[i]*sum);
333 template <
typename Po
intInT>
339 constexpr std::size_t kernel_size = 7;
340 std::vector<float> kernel_values;
341 computeGaussianKernel (kernel_size, 0.0f, kernel_values);
345 Eigen::ArrayXf gaussian_kernel(kernel_size);
348 gaussian_kernel << kernel_values[0], kernel_values[1], kernel_values[2], kernel_values[3], kernel_values[4], kernel_values[5], kernel_values[6];
352 const std::uint32_t width = input_->width;
353 const std::uint32_t height = input_->height;
355 rgb_input_->
resize (width*height);
356 rgb_input_->
width = width;
357 rgb_input_->
height = height;
358 rgb_input_->
is_dense = input_->is_dense;
359 for (std::size_t row_index = 0; row_index < height; ++row_index)
361 for (std::size_t col_index = 0; col_index < width; ++col_index)
363 (*rgb_input_) (col_index, row_index).r = (*input_) (col_index, row_index).r;
364 (*rgb_input_) (col_index, row_index).g = (*input_) (col_index, row_index).g;
365 (*rgb_input_) (col_index, row_index).b = (*input_) (col_index, row_index).b;
372 convolution.
convolve (*smoothed_input_);
375 computeMaxColorGradientsSobel (smoothed_input_);
378 quantizeColorGradients ();
381 filterQuantizedColorGradients ();
386 spreaded_filtered_quantized_color_gradients_,
391 template <
typename Po
intInT>
399 spreaded_filtered_quantized_color_gradients_,
404 template <
typename Po
intInT>
407 std::vector<QuantizedMultiModFeature> & features)
const
409 const std::size_t width = mask.
getWidth ();
410 const std::size_t height = mask.
getHeight ();
412 std::list<Candidate> list1;
413 std::list<Candidate> list2;
416 if (feature_selection_method_ == DISTANCE_MAGNITUDE_SCORE)
418 for (std::size_t row_index = 0; row_index < height; ++row_index)
420 for (std::size_t col_index = 0; col_index < width; ++col_index)
422 if (mask (col_index, row_index) != 0)
424 const GradientXY & gradient = color_gradients_ (col_index, row_index);
425 if (gradient.
magnitude > gradient_magnitude_threshold_feature_extraction_
426 && filtered_quantized_color_gradients_ (col_index, row_index) != 0)
430 candidate.
x =
static_cast<int> (col_index);
431 candidate.
y =
static_cast<int> (row_index);
433 list1.push_back (candidate);
441 if (variable_feature_nr_)
443 list2.push_back (*(list1.begin ()));
445 bool feature_selection_finished =
false;
446 while (!feature_selection_finished)
448 float best_score = 0.0f;
449 auto best_iter = list1.end ();
450 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
453 float smallest_distance = std::numeric_limits<float>::max ();
454 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
456 const float dx =
static_cast<float> (iter1->x) - static_cast<float> (iter2->x);
457 const float dy =
static_cast<float> (iter1->y) - static_cast<float> (iter2->y);
459 const float distance = dx*dx + dy*dy;
461 if (distance < smallest_distance)
463 smallest_distance = distance;
467 const float score = smallest_distance * iter1->gradient.magnitude;
469 if (score > best_score)
477 float min_min_sqr_distance = std::numeric_limits<float>::max ();
478 float max_min_sqr_distance = 0;
479 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
481 float min_sqr_distance = std::numeric_limits<float>::max ();
482 for (
auto iter3 = list2.begin (); iter3 != list2.end (); ++iter3)
487 const float dx =
static_cast<float> (iter2->x) - static_cast<float> (iter3->x);
488 const float dy =
static_cast<float> (iter2->y) - static_cast<float> (iter3->y);
490 const float sqr_distance = dx*dx + dy*dy;
492 if (sqr_distance < min_sqr_distance)
494 min_sqr_distance = sqr_distance;
503 const float dx =
static_cast<float> (iter2->x) - static_cast<float> (best_iter->x);
504 const float dy =
static_cast<float> (iter2->y) - static_cast<float> (best_iter->y);
506 const float sqr_distance = dx*dx + dy*dy;
508 if (sqr_distance < min_sqr_distance)
510 min_sqr_distance = sqr_distance;
514 if (min_sqr_distance < min_min_sqr_distance)
515 min_min_sqr_distance = min_sqr_distance;
516 if (min_sqr_distance > max_min_sqr_distance)
517 max_min_sqr_distance = min_sqr_distance;
522 if (best_iter != list1.end ())
528 if (min_min_sqr_distance < 50)
530 feature_selection_finished =
true;
534 list2.push_back (*best_iter);
540 if (list1.size () <= nr_features)
542 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
546 feature.
x = iter1->x;
547 feature.
y = iter1->y;
549 feature.
quantized_value = filtered_quantized_color_gradients_ (iter1->x, iter1->y);
551 features.push_back (feature);
556 list2.push_back (*(list1.begin ()));
557 while (list2.size () != nr_features)
559 float best_score = 0.0f;
560 auto best_iter = list1.end ();
561 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
564 float smallest_distance = std::numeric_limits<float>::max ();
565 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
567 const float dx =
static_cast<float> (iter1->x) - static_cast<float> (iter2->x);
568 const float dy =
static_cast<float> (iter1->y) - static_cast<float> (iter2->y);
570 const float distance = dx*dx + dy*dy;
572 if (distance < smallest_distance)
574 smallest_distance = distance;
578 const float score = smallest_distance * iter1->gradient.magnitude;
580 if (score > best_score)
587 if (best_iter != list1.end ())
589 list2.push_back (*best_iter);
598 else if (feature_selection_method_ == MASK_BORDER_HIGH_GRADIENTS || feature_selection_method_ == MASK_BORDER_EQUALLY)
601 erode (mask, eroded_mask);
605 for (std::size_t row_index = 0; row_index < height; ++row_index)
607 for (std::size_t col_index = 0; col_index < width; ++col_index)
609 if (diff_mask (col_index, row_index) != 0)
611 const GradientXY & gradient = color_gradients_ (col_index, row_index);
612 if ((feature_selection_method_ == MASK_BORDER_EQUALLY || gradient.
magnitude > gradient_magnitude_threshold_feature_extraction_)
613 && filtered_quantized_color_gradients_ (col_index, row_index) != 0)
617 candidate.
x =
static_cast<int> (col_index);
618 candidate.
y =
static_cast<int> (row_index);
620 list1.push_back (candidate);
628 if (list1.size () <= nr_features)
630 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
634 feature.
x = iter1->x;
635 feature.
y = iter1->y;
637 feature.
quantized_value = filtered_quantized_color_gradients_ (iter1->x, iter1->y);
639 features.push_back (feature);
644 std::size_t distance = list1.size () / nr_features + 1;
645 while (list2.size () != nr_features)
647 const std::size_t sqr_distance = distance*distance;
648 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
650 bool candidate_accepted =
true;
652 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
654 const int dx = iter1->x - iter2->x;
655 const int dy = iter1->y - iter2->y;
656 const unsigned int tmp_distance = dx*dx + dy*dy;
659 if (tmp_distance < sqr_distance)
661 candidate_accepted =
false;
666 if (candidate_accepted)
667 list2.push_back (*iter1);
669 if (list2.size () == nr_features)
676 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
680 feature.
x = iter2->x;
681 feature.
y = iter2->y;
683 feature.
quantized_value = filtered_quantized_color_gradients_ (iter2->x, iter2->y);
685 features.push_back (feature);
690 template <
typename Po
intInT>
void
693 std::vector<QuantizedMultiModFeature> & features)
const
695 const std::size_t width = mask.
getWidth ();
696 const std::size_t height = mask.
getHeight ();
698 std::list<Candidate> list1;
699 std::list<Candidate> list2;
702 for (std::size_t row_index = 0; row_index < height; ++row_index)
704 for (std::size_t col_index = 0; col_index < width; ++col_index)
706 if (mask (col_index, row_index) != 0)
708 const GradientXY & gradient = color_gradients_ (col_index, row_index);
709 if (gradient.
magnitude > gradient_magnitude_threshold_feature_extraction_
710 && filtered_quantized_color_gradients_ (col_index, row_index) != 0)
714 candidate.
x =
static_cast<int> (col_index);
715 candidate.
y =
static_cast<int> (row_index);
717 list1.push_back (candidate);
725 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
729 feature.
x = iter1->x;
730 feature.
y = iter1->y;
732 feature.
quantized_value = filtered_quantized_color_gradients_ (iter1->x, iter1->y);
734 features.push_back (feature);
739 template <
typename Po
intInT>
744 const int width = cloud->
width;
745 const int height = cloud->
height;
747 color_gradients_.resize (width*height);
748 color_gradients_.width = width;
749 color_gradients_.height = height;
751 const float pi = std::tan (1.0f) * 2;
752 for (
int row_index = 0; row_index < height-2; ++row_index)
754 for (
int col_index = 0; col_index < width-2; ++col_index)
756 const int index0 = row_index*width+col_index;
757 const int index_c = row_index*width+col_index+2;
758 const int index_r = (row_index+2)*width+col_index;
762 const unsigned char r0 = (*cloud)[index0].r;
763 const unsigned char g0 = (*cloud)[index0].g;
764 const unsigned char b0 = (*cloud)[index0].b;
766 const unsigned char r_c = (*cloud)[index_c].r;
767 const unsigned char g_c = (*cloud)[index_c].g;
768 const unsigned char b_c = (*cloud)[index_c].b;
770 const unsigned char r_r = (*cloud)[index_r].r;
771 const unsigned char g_r = (*cloud)[index_r].g;
772 const unsigned char b_r = (*cloud)[index_r].b;
774 const float r_dx =
static_cast<float> (r_c) - static_cast<float> (r0);
775 const float g_dx =
static_cast<float> (g_c) - static_cast<float> (g0);
776 const float b_dx =
static_cast<float> (b_c) - static_cast<float> (b0);
778 const float r_dy =
static_cast<float> (r_r) - static_cast<float> (r0);
779 const float g_dy =
static_cast<float> (g_r) - static_cast<float> (g0);
780 const float b_dy =
static_cast<float> (b_r) - static_cast<float> (b0);
782 const float sqr_mag_r = r_dx*r_dx + r_dy*r_dy;
783 const float sqr_mag_g = g_dx*g_dx + g_dy*g_dy;
784 const float sqr_mag_b = b_dx*b_dx + b_dy*b_dy;
786 if (sqr_mag_r > sqr_mag_g && sqr_mag_r > sqr_mag_b)
789 gradient.
magnitude = std::sqrt (sqr_mag_r);
790 gradient.
angle = std::atan2 (r_dy, r_dx) * 180.0f / pi;
791 gradient.
x =
static_cast<float> (col_index);
792 gradient.
y =
static_cast<float> (row_index);
794 color_gradients_ (col_index+1, row_index+1) = gradient;
796 else if (sqr_mag_g > sqr_mag_b)
799 gradient.
magnitude = std::sqrt (sqr_mag_g);
800 gradient.
angle = std::atan2 (g_dy, g_dx) * 180.0f / pi;
801 gradient.
x =
static_cast<float> (col_index);
802 gradient.
y =
static_cast<float> (row_index);
804 color_gradients_ (col_index+1, row_index+1) = gradient;
809 gradient.
magnitude = std::sqrt (sqr_mag_b);
810 gradient.
angle = std::atan2 (b_dy, b_dx) * 180.0f / pi;
811 gradient.
x =
static_cast<float> (col_index);
812 gradient.
y =
static_cast<float> (row_index);
814 color_gradients_ (col_index+1, row_index+1) = gradient;
817 assert (color_gradients_ (col_index+1, row_index+1).angle >= -180 &&
818 color_gradients_ (col_index+1, row_index+1).angle <= 180);
826 template <
typename Po
intInT>
831 const int width = cloud->
width;
832 const int height = cloud->
height;
834 color_gradients_.resize (width*height);
835 color_gradients_.width = width;
836 color_gradients_.height = height;
838 const float pi = tanf (1.0f) * 2.0f;
839 for (
int row_index = 1; row_index < height-1; ++row_index)
841 for (
int col_index = 1; col_index < width-1; ++col_index)
843 const int r7 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index-1)].r);
844 const int g7 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index-1)].g);
845 const int b7 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index-1)].b);
846 const int r8 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index)].r);
847 const int g8 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index)].g);
848 const int b8 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index)].b);
849 const int r9 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index+1)].r);
850 const int g9 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index+1)].g);
851 const int b9 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index+1)].b);
852 const int r4 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index-1)].r);
853 const int g4 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index-1)].g);
854 const int b4 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index-1)].b);
855 const int r6 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index+1)].r);
856 const int g6 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index+1)].g);
857 const int b6 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index+1)].b);
858 const int r1 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index-1)].r);
859 const int g1 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index-1)].g);
860 const int b1 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index-1)].b);
861 const int r2 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index)].r);
862 const int g2 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index)].g);
863 const int b2 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index)].b);
864 const int r3 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index+1)].r);
865 const int g3 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index+1)].g);
866 const int b3 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index+1)].b);
891 const int r_dx = r9 + 2*r6 + r3 - (r7 + 2*r4 + r1);
892 const int r_dy = r1 + 2*r2 + r3 - (r7 + 2*r8 + r9);
893 const int g_dx = g9 + 2*g6 + g3 - (g7 + 2*g4 + g1);
894 const int g_dy = g1 + 2*g2 + g3 - (g7 + 2*g8 + g9);
895 const int b_dx = b9 + 2*b6 + b3 - (b7 + 2*b4 + b1);
896 const int b_dy = b1 + 2*b2 + b3 - (b7 + 2*b8 + b9);
898 const int sqr_mag_r = r_dx*r_dx + r_dy*r_dy;
899 const int sqr_mag_g = g_dx*g_dx + g_dy*g_dy;
900 const int sqr_mag_b = b_dx*b_dx + b_dy*b_dy;
902 if (sqr_mag_r > sqr_mag_g && sqr_mag_r > sqr_mag_b)
905 gradient.
magnitude = std::sqrt (static_cast<float> (sqr_mag_r));
906 gradient.
angle = std::atan2 (static_cast<float> (r_dy), static_cast<float> (r_dx)) * 180.0f / pi;
907 if (gradient.
angle < -180.0f) gradient.
angle += 360.0f;
908 if (gradient.
angle >= 180.0f) gradient.
angle -= 360.0f;
909 gradient.
x =
static_cast<float> (col_index);
910 gradient.
y =
static_cast<float> (row_index);
912 color_gradients_ (col_index, row_index) = gradient;
914 else if (sqr_mag_g > sqr_mag_b)
917 gradient.
magnitude = std::sqrt (static_cast<float> (sqr_mag_g));
918 gradient.
angle = std::atan2 (static_cast<float> (g_dy), static_cast<float> (g_dx)) * 180.0f / pi;
919 if (gradient.
angle < -180.0f) gradient.
angle += 360.0f;
920 if (gradient.
angle >= 180.0f) gradient.
angle -= 360.0f;
921 gradient.
x =
static_cast<float> (col_index);
922 gradient.
y =
static_cast<float> (row_index);
924 color_gradients_ (col_index, row_index) = gradient;
929 gradient.
magnitude = std::sqrt (static_cast<float> (sqr_mag_b));
930 gradient.
angle = std::atan2 (static_cast<float> (b_dy), static_cast<float> (b_dx)) * 180.0f / pi;
931 if (gradient.
angle < -180.0f) gradient.
angle += 360.0f;
932 if (gradient.
angle >= 180.0f) gradient.
angle -= 360.0f;
933 gradient.
x =
static_cast<float> (col_index);
934 gradient.
y =
static_cast<float> (row_index);
936 color_gradients_ (col_index, row_index) = gradient;
939 assert (color_gradients_ (col_index, row_index).angle >= -180 &&
940 color_gradients_ (col_index, row_index).angle <= 180);
948 template <
typename Po
intInT>
965 const std::size_t width = input_->width;
966 const std::size_t height = input_->height;
968 quantized_color_gradients_.resize (width, height);
970 constexpr
float angleScale = 16.0f / 360.0f;
974 for (std::size_t row_index = 0; row_index < height; ++row_index)
976 for (std::size_t col_index = 0; col_index < width; ++col_index)
978 if (color_gradients_ (col_index, row_index).magnitude < gradient_magnitude_threshold_)
980 quantized_color_gradients_ (col_index, row_index) = 0;
984 const float angle = 11.25f + color_gradients_ (col_index, row_index).angle + 180.0f;
985 const int quantized_value = (
static_cast<int> (angle * angleScale)) & 7;
986 quantized_color_gradients_ (col_index, row_index) =
static_cast<unsigned char> (quantized_value + 1);
1011 template <
typename Po
intInT>
1016 const std::size_t width = input_->width;
1017 const std::size_t height = input_->height;
1019 filtered_quantized_color_gradients_.resize (width, height);
1022 for (std::size_t row_index = 1; row_index < height-1; ++row_index)
1024 for (std::size_t col_index = 1; col_index < width-1; ++col_index)
1026 unsigned char histogram[9] = {0,0,0,0,0,0,0,0,0};
1029 const unsigned char * data_ptr = quantized_color_gradients_.getData () + (row_index-1)*width+col_index-1;
1030 assert (data_ptr[0] < 9 && data_ptr[1] < 9 && data_ptr[2] < 9);
1031 ++histogram[data_ptr[0]];
1032 ++histogram[data_ptr[1]];
1033 ++histogram[data_ptr[2]];
1036 const unsigned char * data_ptr = quantized_color_gradients_.getData () + row_index*width+col_index-1;
1037 assert (data_ptr[0] < 9 && data_ptr[1] < 9 && data_ptr[2] < 9);
1038 ++histogram[data_ptr[0]];
1039 ++histogram[data_ptr[1]];
1040 ++histogram[data_ptr[2]];
1043 const unsigned char * data_ptr = quantized_color_gradients_.getData () + (row_index+1)*width+col_index-1;
1044 assert (data_ptr[0] < 9 && data_ptr[1] < 9 && data_ptr[2] < 9);
1045 ++histogram[data_ptr[0]];
1046 ++histogram[data_ptr[1]];
1047 ++histogram[data_ptr[2]];
1050 unsigned char max_hist_value = 0;
1051 int max_hist_index = -1;
1062 if (max_hist_value < histogram[1]) {max_hist_index = 0; max_hist_value = histogram[1];}
1063 if (max_hist_value < histogram[2]) {max_hist_index = 1; max_hist_value = histogram[2];}
1064 if (max_hist_value < histogram[3]) {max_hist_index = 2; max_hist_value = histogram[3];}
1065 if (max_hist_value < histogram[4]) {max_hist_index = 3; max_hist_value = histogram[4];}
1066 if (max_hist_value < histogram[5]) {max_hist_index = 4; max_hist_value = histogram[5];}
1067 if (max_hist_value < histogram[6]) {max_hist_index = 5; max_hist_value = histogram[6];}
1068 if (max_hist_value < histogram[7]) {max_hist_index = 6; max_hist_value = histogram[7];}
1069 if (max_hist_value < histogram[8]) {max_hist_index = 7; max_hist_value = histogram[8];}
1071 if (max_hist_index != -1 && max_hist_value >= 5)
1072 filtered_quantized_color_gradients_ (col_index, row_index) =
static_cast<unsigned char> (0x1 << max_hist_index);
1074 filtered_quantized_color_gradients_ (col_index, row_index) = 0;
1081 template <
typename Po
intInT>
1087 const std::size_t width = mask_in.
getWidth ();
1088 const std::size_t height = mask_in.
getHeight ();
1090 mask_out.
resize (width, height);
1092 for (std::size_t row_index = 1; row_index < height-1; ++row_index)
1094 for (std::size_t col_index = 1; col_index < width-1; ++col_index)
1096 if (mask_in (col_index, row_index-1) == 0 ||
1097 mask_in (col_index-1, row_index) == 0 ||
1098 mask_in (col_index+1, row_index) == 0 ||
1099 mask_in (col_index, row_index+1) == 0)
1101 mask_out (col_index, row_index) = 0;
1105 mask_out (col_index, row_index) = 255;
QuantizedMap & getQuantizedMap() override
Returns a reference to the internally computed quantized map.
static void spreadQuantizedMap(const QuantizedMap &input_map, QuantizedMap &output_map, std::size_t spreading_size)
void extractAllFeatures(const MaskMap &mask, std::size_t nr_features, std::size_t modalityIndex, std::vector< QuantizedMultiModFeature > &features) const override
Extracts all possible features from the modality within the specified mask.
shared_ptr< PointCloud< PointT > > Ptr
Feature that defines a position and quantized value in a specific modality.
void computeMaxColorGradientsSobel(const typename pcl::PointCloud< pcl::RGB >::ConstPtr &cloud)
Computes the max-RGB gradients for the specified cloud using sobel.
void convolve(const Eigen::ArrayXf &h_kernel, const Eigen::ArrayXf &v_kernel, PointCloudOut &output)
Convolve point cloud with an horizontal kernel along rows then vertical kernel along columns : convol...
void quantizeColorGradients()
Quantizes the color gradients.
void setFeatureSelectionMethod(const FeatureSelectionMethod method)
Sets the feature selection method.
std::size_t modality_index
the index of the corresponding modality.
unsigned char quantized_value
the quantized value attached to the feature.
void setKernel(const Eigen::ArrayXf &kernel)
Set convolving kernel.
A point structure representing Euclidean xyz coordinates, and the intensity value.
GradientXY gradient
The gradient.
void setSpreadingSize(const std::size_t spreading_size)
Sets the spreading size for spreading the quantized data.
std::uint32_t width
The point cloud width (if organized as an image-structure).
A structure representing RGB color information.
~ColorGradientModality() override
Destructor.
Convolution is a mathematical operation on two functions f and g, producing a third function that is ...
QuantizedMap & getSpreadedQuantizedMap() override
Returns a reference to the internally computed spread quantized map.
void setInputCloud(const PointCloudInConstPtr &cloud)
Provide a pointer to the input dataset.
ColorGradientModality()
Constructor.
void setGradientMagnitudeThresholdForFeatureExtraction(const float threshold)
Sets the threshold for the gradient magnitude which is used for feature extraction.
void computeMaxColorGradients(const typename pcl::PointCloud< pcl::RGB >::ConstPtr &cloud)
Computes the max-RGB gradients for the specified cloud.
void setInputCloud(const typename PointCloudIn::ConstPtr &cloud) override
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method) ...
Interface for a quantizable modality.
void resize(std::size_t count)
Resizes the container to contain count elements.
std::uint32_t height
The point cloud height (if organized as an image-structure).
virtual void processInputDataFromFiltered()
Processes the input data assuming that everything up to filtering is already done/available (so only ...
void resize(std::size_t width, std::size_t height)
Modality based on max-RGB gradients.
void filterQuantizedColorGradients()
Filters the quantized gradients.
FeatureSelectionMethod
Different methods for feature selection/extraction.
void extractFeatures(const MaskMap &mask, std::size_t nr_features, std::size_t modalityIndex, std::vector< QuantizedMultiModFeature > &features) const override
Extracts features from this modality within the specified mask.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields)...
static PCL_NODISCARD MaskMap getDifferenceMask(const MaskMap &mask0, const MaskMap &mask1)
shared_ptr< const PointCloud< PointRGBT > > ConstPtr
virtual void processInputData()
Processes the input data (smoothing, computing gradients, quantizing, filtering, spreading).
PointCloudConstPtr input_
The input point cloud dataset.
static void erode(const pcl::MaskMap &mask_in, pcl::MaskMap &mask_out)
Erodes a mask.
void setGradientMagnitudeThreshold(const float threshold)
Sets the threshold for the gradient magnitude which is used when quantizing the data.
bool operator<(const Candidate &rhs) const
Operator for comparing to candidates (by magnitude of the gradient).
void computeGaussianKernel(const std::size_t kernel_size, const float sigma, std::vector< float > &kernel_values)
Computes the Gaussian kernel used for smoothing.
void setVariableFeatureNr(const bool enabled)
Sets whether variable feature numbers for feature extraction is enabled.
pcl::PointCloud< pcl::GradientXY > & getMaxColorGradients()
Returns a point cloud containing the max-RGB gradients.
std::size_t getHeight() const
Candidate for a feature (used in feature extraction methods).
std::size_t getWidth() const