40 #include <pcl/recognition/quantizable_modality.h>
42 #include <pcl/pcl_base.h>
43 #include <pcl/point_cloud.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;
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
290 computeGaussianKernel (
const std::size_t kernel_size,
const float sigma, std::vector <float> & kernel_values)
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;
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;
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)
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;
Modality based on max-RGB gradients.
void filterQuantizedColorGradients()
Filters the quantized gradients.
pcl::PointCloud< pcl::GradientXY > & getMaxColorGradients()
Returns a point cloud containing the max-RGB gradients.
static void erode(const pcl::MaskMap &mask_in, pcl::MaskMap &mask_out)
Erodes a mask.
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.
FeatureSelectionMethod
Different methods for feature selection/extraction.
@ DISTANCE_MAGNITUDE_SCORE
@ MASK_BORDER_HIGH_GRADIENTS
void setGradientMagnitudeThresholdForFeatureExtraction(const float threshold)
Sets the threshold for the gradient magnitude which is used for feature extraction.
void computeMaxColorGradientsSobel(const typename pcl::PointCloud< pcl::RGB >::ConstPtr &cloud)
Computes the max-RGB gradients for the specified cloud using sobel.
void setVariableFeatureNr(const bool enabled)
Sets whether variable feature numbers for feature extraction is enabled.
void setSpreadingSize(const std::size_t spreading_size)
Sets the spreading size for spreading the quantized data.
void computeMaxColorGradients(const typename pcl::PointCloud< pcl::RGB >::ConstPtr &cloud)
Computes the max-RGB gradients for the specified cloud.
void setFeatureSelectionMethod(const FeatureSelectionMethod method)
Sets the feature selection method.
virtual void processInputDataFromFiltered()
Processes the input data assuming that everything up to filtering is already done/available (so only ...
virtual void processInputData()
Processes the input data (smoothing, computing gradients, quantizing, filtering, spreading).
void quantizeColorGradients()
Quantizes the color gradients.
ColorGradientModality()
Constructor.
void setInputCloud(const typename PointCloudIn::ConstPtr &cloud) override
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method)
QuantizedMap & getSpreadedQuantizedMap() override
Returns a reference to the internally computed spread quantized map.
~ColorGradientModality() override
Destructor.
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.
void computeGaussianKernel(const std::size_t kernel_size, const float sigma, std::vector< float > &kernel_values)
Computes the Gaussian kernel used for smoothing.
QuantizedMap & getQuantizedMap() override
Returns a reference to the internally computed quantized map.
void setGradientMagnitudeThreshold(const float threshold)
Sets the threshold for the gradient magnitude which is used when quantizing the data.
std::size_t getWidth() const
void resize(std::size_t width, std::size_t height)
std::size_t getHeight() const
static PCL_NODISCARD MaskMap getDifferenceMask(const MaskMap &mask0, const MaskMap &mask1)
PointCloudConstPtr input_
The input point cloud dataset.
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
void resize(std::size_t count)
Resizes the container to contain count elements.
std::uint32_t width
The point cloud width (if organized as an image-structure).
std::uint32_t height
The point cloud height (if organized as an image-structure).
shared_ptr< PointCloud< PointT > > Ptr
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)
Convolution is a mathematical operation on two functions f and g, producing a third function that is ...
void setInputCloud(const PointCloudInConstPtr &cloud)
Provide a pointer to the input dataset.
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 setBordersPolicy(int policy)
Set the borders policy.
void setKernel(const Eigen::ArrayXf &kernel)
Set convolving kernel.
Defines all the PCL implemented PointT point type structures.
float distance(const PointT &p1, const PointT &p2)
Candidate for a feature (used in feature extraction methods).
GradientXY gradient
The gradient.
bool operator<(const Candidate &rhs) const
Operator for comparing to candidates (by magnitude of the gradient).
A point structure representing Euclidean xyz coordinates, and the intensity value.
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.
A structure representing RGB color information.