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_;
252 float gradient_magnitude_threshold_;
254 float gradient_magnitude_threshold_feature_extraction_;
260 std::size_t spreading_size_;
274 template <
typename Po
intInT>
277 : variable_feature_nr_ (false)
279 , feature_selection_method_ (DISTANCE_MAGNITUDE_SCORE)
280 , gradient_magnitude_threshold_ (10.0f)
281 , gradient_magnitude_threshold_feature_extraction_ (55.0f)
282 , spreading_size_ (8)
287 template <
typename Po
intInT>
294 template <
typename Po
intInT>
void
296 computeGaussianKernel (
const std::size_t kernel_size,
const float sigma, std::vector <float> & kernel_values)
299 const int n = int (kernel_size);
300 const int SMALL_GAUSSIAN_SIZE = 7;
301 static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
304 {0.25f, 0.5f, 0.25f},
305 {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
306 {0.03125f, 0.109375f, 0.21875f, 0.28125f, 0.21875f, 0.109375f, 0.03125f}
309 const float* fixed_kernel = n % 2 == 1 && n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ?
310 small_gaussian_tab[n>>1] :
nullptr;
314 kernel_values.resize (n);
315 float* cf = &(kernel_values[0]);
318 double sigmaX = sigma > 0 ? sigma : ((n-1)*0.5 - 1)*0.3 + 0.8;
319 double scale2X = -0.5/(sigmaX*sigmaX);
322 for(
int i = 0; i < n; i++ )
324 double x = i - (n-1)*0.5;
325 double t = fixed_kernel ? double (fixed_kernel[i]) : std::exp (scale2X*x*x);
332 for (
int i = 0; i < n; i++ )
334 cf[i] = float (cf[i]*sum);
339 template <
typename Po
intInT>
345 const std::size_t kernel_size = 7;
346 std::vector<float> kernel_values;
347 computeGaussianKernel (kernel_size, 0.0f, kernel_values);
351 Eigen::ArrayXf gaussian_kernel(kernel_size);
354 gaussian_kernel << kernel_values[0], kernel_values[1], kernel_values[2], kernel_values[3], kernel_values[4], kernel_values[5], kernel_values[6];
358 const std::uint32_t width = input_->width;
359 const std::uint32_t height = input_->height;
361 rgb_input_->
resize (width*height);
362 rgb_input_->
width = width;
363 rgb_input_->
height = height;
364 rgb_input_->
is_dense = input_->is_dense;
365 for (std::size_t row_index = 0; row_index < height; ++row_index)
367 for (std::size_t col_index = 0; col_index < width; ++col_index)
369 (*rgb_input_) (col_index, row_index).r = (*input_) (col_index, row_index).r;
370 (*rgb_input_) (col_index, row_index).g = (*input_) (col_index, row_index).g;
371 (*rgb_input_) (col_index, row_index).b = (*input_) (col_index, row_index).b;
378 convolution.
convolve (*smoothed_input_);
381 computeMaxColorGradientsSobel (smoothed_input_);
384 quantizeColorGradients ();
387 filterQuantizedColorGradients ();
392 spreaded_filtered_quantized_color_gradients_,
397 template <
typename Po
intInT>
405 spreaded_filtered_quantized_color_gradients_,
410 template <
typename Po
intInT>
413 std::vector<QuantizedMultiModFeature> & features)
const
415 const std::size_t width = mask.
getWidth ();
416 const std::size_t height = mask.
getHeight ();
418 std::list<Candidate> list1;
419 std::list<Candidate> list2;
422 if (feature_selection_method_ == DISTANCE_MAGNITUDE_SCORE)
424 for (std::size_t row_index = 0; row_index < height; ++row_index)
426 for (std::size_t col_index = 0; col_index < width; ++col_index)
428 if (mask (col_index, row_index) != 0)
430 const GradientXY & gradient = color_gradients_ (col_index, row_index);
431 if (gradient.
magnitude > gradient_magnitude_threshold_feature_extraction_
432 && filtered_quantized_color_gradients_ (col_index, row_index) != 0)
436 candidate.
x =
static_cast<int> (col_index);
437 candidate.
y =
static_cast<int> (row_index);
439 list1.push_back (candidate);
447 if (variable_feature_nr_)
449 list2.push_back (*(list1.begin ()));
451 bool feature_selection_finished =
false;
452 while (!feature_selection_finished)
454 float best_score = 0.0f;
455 typename std::list<Candidate>::iterator best_iter = list1.end ();
456 for (
typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
459 float smallest_distance = std::numeric_limits<float>::max ();
460 for (
typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
462 const float dx =
static_cast<float> (iter1->x) -
static_cast<float> (iter2->x);
463 const float dy =
static_cast<float> (iter1->y) -
static_cast<float> (iter2->y);
465 const float distance = dx*dx + dy*dy;
473 const float score = smallest_distance * iter1->gradient.magnitude;
475 if (score > best_score)
483 float min_min_sqr_distance = std::numeric_limits<float>::max ();
484 float max_min_sqr_distance = 0;
485 for (
typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
487 float min_sqr_distance = std::numeric_limits<float>::max ();
488 for (
typename std::list<Candidate>::iterator iter3 = list2.begin (); iter3 != list2.end (); ++iter3)
493 const float dx =
static_cast<float> (iter2->x) -
static_cast<float> (iter3->x);
494 const float dy =
static_cast<float> (iter2->y) -
static_cast<float> (iter3->y);
496 const float sqr_distance = dx*dx + dy*dy;
498 if (sqr_distance < min_sqr_distance)
500 min_sqr_distance = sqr_distance;
509 const float dx =
static_cast<float> (iter2->x) -
static_cast<float> (best_iter->x);
510 const float dy =
static_cast<float> (iter2->y) -
static_cast<float> (best_iter->y);
512 const float sqr_distance = dx*dx + dy*dy;
514 if (sqr_distance < min_sqr_distance)
516 min_sqr_distance = sqr_distance;
520 if (min_sqr_distance < min_min_sqr_distance)
521 min_min_sqr_distance = min_sqr_distance;
522 if (min_sqr_distance > max_min_sqr_distance)
523 max_min_sqr_distance = min_sqr_distance;
528 if (best_iter != list1.end ())
534 if (min_min_sqr_distance < 50)
536 feature_selection_finished =
true;
540 list2.push_back (*best_iter);
546 if (list1.size () <= nr_features)
548 for (
typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
552 feature.
x = iter1->x;
553 feature.
y = iter1->y;
555 feature.
quantized_value = filtered_quantized_color_gradients_ (iter1->x, iter1->y);
557 features.push_back (feature);
562 list2.push_back (*(list1.begin ()));
563 while (list2.size () != nr_features)
565 float best_score = 0.0f;
566 typename std::list<Candidate>::iterator best_iter = list1.end ();
567 for (
typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
570 float smallest_distance = std::numeric_limits<float>::max ();
571 for (
typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
573 const float dx =
static_cast<float> (iter1->x) -
static_cast<float> (iter2->x);
574 const float dy =
static_cast<float> (iter1->y) -
static_cast<float> (iter2->y);
576 const float distance = dx*dx + dy*dy;
584 const float score = smallest_distance * iter1->gradient.magnitude;
586 if (score > best_score)
593 if (best_iter != list1.end ())
595 list2.push_back (*best_iter);
604 else if (feature_selection_method_ == MASK_BORDER_HIGH_GRADIENTS || feature_selection_method_ == MASK_BORDER_EQUALLY)
607 erode (mask, eroded_mask);
611 for (std::size_t row_index = 0; row_index < height; ++row_index)
613 for (std::size_t col_index = 0; col_index < width; ++col_index)
615 if (diff_mask (col_index, row_index) != 0)
617 const GradientXY & gradient = color_gradients_ (col_index, row_index);
618 if ((feature_selection_method_ == MASK_BORDER_EQUALLY || gradient.
magnitude > gradient_magnitude_threshold_feature_extraction_)
619 && filtered_quantized_color_gradients_ (col_index, row_index) != 0)
623 candidate.
x =
static_cast<int> (col_index);
624 candidate.
y =
static_cast<int> (row_index);
626 list1.push_back (candidate);
634 if (list1.size () <= nr_features)
636 for (
typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
640 feature.
x = iter1->x;
641 feature.
y = iter1->y;
643 feature.
quantized_value = filtered_quantized_color_gradients_ (iter1->x, iter1->y);
645 features.push_back (feature);
650 std::size_t
distance = list1.size () / nr_features + 1;
651 while (list2.size () != nr_features)
654 for (
typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
656 bool candidate_accepted =
true;
658 for (
typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
660 const int dx = iter1->x - iter2->x;
661 const int dy = iter1->y - iter2->y;
662 const unsigned int tmp_distance = dx*dx + dy*dy;
665 if (tmp_distance < sqr_distance)
667 candidate_accepted =
false;
672 if (candidate_accepted)
673 list2.push_back (*iter1);
675 if (list2.size () == nr_features)
682 for (
typename std::list<Candidate>::iterator iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
686 feature.
x = iter2->x;
687 feature.
y = iter2->y;
689 feature.
quantized_value = filtered_quantized_color_gradients_ (iter2->x, iter2->y);
691 features.push_back (feature);
696 template <
typename Po
intInT>
void
699 std::vector<QuantizedMultiModFeature> & features)
const
701 const std::size_t width = mask.
getWidth ();
702 const std::size_t height = mask.
getHeight ();
704 std::list<Candidate> list1;
705 std::list<Candidate> list2;
708 for (std::size_t row_index = 0; row_index < height; ++row_index)
710 for (std::size_t col_index = 0; col_index < width; ++col_index)
712 if (mask (col_index, row_index) != 0)
714 const GradientXY & gradient = color_gradients_ (col_index, row_index);
715 if (gradient.
magnitude > gradient_magnitude_threshold_feature_extraction_
716 && filtered_quantized_color_gradients_ (col_index, row_index) != 0)
720 candidate.
x =
static_cast<int> (col_index);
721 candidate.
y =
static_cast<int> (row_index);
723 list1.push_back (candidate);
731 for (
typename std::list<Candidate>::iterator iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
735 feature.
x = iter1->x;
736 feature.
y = iter1->y;
738 feature.
quantized_value = filtered_quantized_color_gradients_ (iter1->x, iter1->y);
740 features.push_back (feature);
745 template <
typename Po
intInT>
750 const int width = cloud->
width;
751 const int height = cloud->
height;
753 color_gradients_.resize (width*height);
754 color_gradients_.width = width;
755 color_gradients_.height = height;
757 const float pi = tan (1.0f) * 2;
758 for (
int row_index = 0; row_index < height-2; ++row_index)
760 for (
int col_index = 0; col_index < width-2; ++col_index)
762 const int index0 = row_index*width+col_index;
763 const int index_c = row_index*width+col_index+2;
764 const int index_r = (row_index+2)*width+col_index;
768 const unsigned char r0 = (*cloud)[index0].r;
769 const unsigned char g0 = (*cloud)[index0].g;
770 const unsigned char b0 = (*cloud)[index0].b;
772 const unsigned char r_c = (*cloud)[index_c].r;
773 const unsigned char g_c = (*cloud)[index_c].g;
774 const unsigned char b_c = (*cloud)[index_c].b;
776 const unsigned char r_r = (*cloud)[index_r].r;
777 const unsigned char g_r = (*cloud)[index_r].g;
778 const unsigned char b_r = (*cloud)[index_r].b;
780 const float r_dx =
static_cast<float> (r_c) -
static_cast<float> (r0);
781 const float g_dx =
static_cast<float> (g_c) -
static_cast<float> (g0);
782 const float b_dx =
static_cast<float> (b_c) -
static_cast<float> (b0);
784 const float r_dy =
static_cast<float> (r_r) -
static_cast<float> (r0);
785 const float g_dy =
static_cast<float> (g_r) -
static_cast<float> (g0);
786 const float b_dy =
static_cast<float> (b_r) -
static_cast<float> (b0);
788 const float sqr_mag_r = r_dx*r_dx + r_dy*r_dy;
789 const float sqr_mag_g = g_dx*g_dx + g_dy*g_dy;
790 const float sqr_mag_b = b_dx*b_dx + b_dy*b_dy;
792 if (sqr_mag_r > sqr_mag_g && sqr_mag_r > sqr_mag_b)
796 gradient.
angle = std::atan2 (r_dy, r_dx) * 180.0f / pi;
797 gradient.
x =
static_cast<float> (col_index);
798 gradient.
y =
static_cast<float> (row_index);
800 color_gradients_ (col_index+1, row_index+1) = gradient;
802 else if (sqr_mag_g > sqr_mag_b)
806 gradient.
angle = std::atan2 (g_dy, g_dx) * 180.0f / pi;
807 gradient.
x =
static_cast<float> (col_index);
808 gradient.
y =
static_cast<float> (row_index);
810 color_gradients_ (col_index+1, row_index+1) = gradient;
816 gradient.
angle = std::atan2 (b_dy, b_dx) * 180.0f / pi;
817 gradient.
x =
static_cast<float> (col_index);
818 gradient.
y =
static_cast<float> (row_index);
820 color_gradients_ (col_index+1, row_index+1) = gradient;
823 assert (color_gradients_ (col_index+1, row_index+1).angle >= -180 &&
824 color_gradients_ (col_index+1, row_index+1).angle <= 180);
832 template <
typename Po
intInT>
837 const int width = cloud->
width;
838 const int height = cloud->
height;
840 color_gradients_.resize (width*height);
841 color_gradients_.width = width;
842 color_gradients_.height = height;
844 const float pi = tanf (1.0f) * 2.0f;
845 for (
int row_index = 1; row_index < height-1; ++row_index)
847 for (
int col_index = 1; col_index < width-1; ++col_index)
849 const int r7 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index-1)].r);
850 const int g7 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index-1)].g);
851 const int b7 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index-1)].b);
852 const int r8 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index)].r);
853 const int g8 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index)].g);
854 const int b8 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index)].b);
855 const int r9 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index+1)].r);
856 const int g9 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index+1)].g);
857 const int b9 =
static_cast<int> ((*cloud)[(row_index-1)*width + (col_index+1)].b);
858 const int r4 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index-1)].r);
859 const int g4 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index-1)].g);
860 const int b4 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index-1)].b);
861 const int r6 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index+1)].r);
862 const int g6 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index+1)].g);
863 const int b6 =
static_cast<int> ((*cloud)[(row_index)*width + (col_index+1)].b);
864 const int r1 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index-1)].r);
865 const int g1 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index-1)].g);
866 const int b1 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index-1)].b);
867 const int r2 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index)].r);
868 const int g2 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index)].g);
869 const int b2 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index)].b);
870 const int r3 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index+1)].r);
871 const int g3 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index+1)].g);
872 const int b3 =
static_cast<int> ((*cloud)[(row_index+1)*width + (col_index+1)].b);
897 const int r_dx = r9 + 2*r6 + r3 - (r7 + 2*r4 + r1);
898 const int r_dy = r1 + 2*r2 + r3 - (r7 + 2*r8 + r9);
899 const int g_dx = g9 + 2*g6 + g3 - (g7 + 2*g4 + g1);
900 const int g_dy = g1 + 2*g2 + g3 - (g7 + 2*g8 + g9);
901 const int b_dx = b9 + 2*b6 + b3 - (b7 + 2*b4 + b1);
902 const int b_dy = b1 + 2*b2 + b3 - (b7 + 2*b8 + b9);
904 const int sqr_mag_r = r_dx*r_dx + r_dy*r_dy;
905 const int sqr_mag_g = g_dx*g_dx + g_dy*g_dy;
906 const int sqr_mag_b = b_dx*b_dx + b_dy*b_dy;
908 if (sqr_mag_r > sqr_mag_g && sqr_mag_r > sqr_mag_b)
911 gradient.
magnitude = std::sqrt (
static_cast<float> (sqr_mag_r));
912 gradient.
angle = std::atan2 (
static_cast<float> (r_dy),
static_cast<float> (r_dx)) * 180.0f / pi;
913 if (gradient.
angle < -180.0f) gradient.
angle += 360.0f;
914 if (gradient.
angle >= 180.0f) gradient.
angle -= 360.0f;
915 gradient.
x =
static_cast<float> (col_index);
916 gradient.
y =
static_cast<float> (row_index);
918 color_gradients_ (col_index, row_index) = gradient;
920 else if (sqr_mag_g > sqr_mag_b)
923 gradient.
magnitude = std::sqrt (
static_cast<float> (sqr_mag_g));
924 gradient.
angle = std::atan2 (
static_cast<float> (g_dy),
static_cast<float> (g_dx)) * 180.0f / pi;
925 if (gradient.
angle < -180.0f) gradient.
angle += 360.0f;
926 if (gradient.
angle >= 180.0f) gradient.
angle -= 360.0f;
927 gradient.
x =
static_cast<float> (col_index);
928 gradient.
y =
static_cast<float> (row_index);
930 color_gradients_ (col_index, row_index) = gradient;
935 gradient.
magnitude = std::sqrt (
static_cast<float> (sqr_mag_b));
936 gradient.
angle = std::atan2 (
static_cast<float> (b_dy),
static_cast<float> (b_dx)) * 180.0f / pi;
937 if (gradient.
angle < -180.0f) gradient.
angle += 360.0f;
938 if (gradient.
angle >= 180.0f) gradient.
angle -= 360.0f;
939 gradient.
x =
static_cast<float> (col_index);
940 gradient.
y =
static_cast<float> (row_index);
942 color_gradients_ (col_index, row_index) = gradient;
945 assert (color_gradients_ (col_index, row_index).angle >= -180 &&
946 color_gradients_ (col_index, row_index).angle <= 180);
954 template <
typename Po
intInT>
971 const std::size_t width = input_->width;
972 const std::size_t height = input_->height;
974 quantized_color_gradients_.resize (width, height);
976 const float angleScale = 16.0f/360.0f;
980 for (std::size_t row_index = 0; row_index < height; ++row_index)
982 for (std::size_t col_index = 0; col_index < width; ++col_index)
984 if (color_gradients_ (col_index, row_index).magnitude < gradient_magnitude_threshold_)
986 quantized_color_gradients_ (col_index, row_index) = 0;
990 const float angle = 11.25f + color_gradients_ (col_index, row_index).angle + 180.0f;
991 const int quantized_value = (
static_cast<int> (angle * angleScale)) & 7;
992 quantized_color_gradients_ (col_index, row_index) =
static_cast<unsigned char> (quantized_value + 1);
1017 template <
typename Po
intInT>
1022 const std::size_t width = input_->width;
1023 const std::size_t height = input_->height;
1025 filtered_quantized_color_gradients_.resize (width, height);
1028 for (std::size_t row_index = 1; row_index < height-1; ++row_index)
1030 for (std::size_t col_index = 1; col_index < width-1; ++col_index)
1032 unsigned char histogram[9] = {0,0,0,0,0,0,0,0,0};
1035 const unsigned char * data_ptr = quantized_color_gradients_.getData () + (row_index-1)*width+col_index-1;
1036 assert (data_ptr[0] < 9 && data_ptr[1] < 9 && data_ptr[2] < 9);
1037 ++histogram[data_ptr[0]];
1038 ++histogram[data_ptr[1]];
1039 ++histogram[data_ptr[2]];
1042 const unsigned char * data_ptr = quantized_color_gradients_.getData () + row_index*width+col_index-1;
1043 assert (data_ptr[0] < 9 && data_ptr[1] < 9 && data_ptr[2] < 9);
1044 ++histogram[data_ptr[0]];
1045 ++histogram[data_ptr[1]];
1046 ++histogram[data_ptr[2]];
1049 const unsigned char * data_ptr = quantized_color_gradients_.getData () + (row_index+1)*width+col_index-1;
1050 assert (data_ptr[0] < 9 && data_ptr[1] < 9 && data_ptr[2] < 9);
1051 ++histogram[data_ptr[0]];
1052 ++histogram[data_ptr[1]];
1053 ++histogram[data_ptr[2]];
1056 unsigned char max_hist_value = 0;
1057 int max_hist_index = -1;
1068 if (max_hist_value < histogram[1]) {max_hist_index = 0; max_hist_value = histogram[1];}
1069 if (max_hist_value < histogram[2]) {max_hist_index = 1; max_hist_value = histogram[2];}
1070 if (max_hist_value < histogram[3]) {max_hist_index = 2; max_hist_value = histogram[3];}
1071 if (max_hist_value < histogram[4]) {max_hist_index = 3; max_hist_value = histogram[4];}
1072 if (max_hist_value < histogram[5]) {max_hist_index = 4; max_hist_value = histogram[5];}
1073 if (max_hist_value < histogram[6]) {max_hist_index = 5; max_hist_value = histogram[6];}
1074 if (max_hist_value < histogram[7]) {max_hist_index = 6; max_hist_value = histogram[7];}
1075 if (max_hist_value < histogram[8]) {max_hist_index = 7; max_hist_value = histogram[8];}
1077 if (max_hist_index != -1 && max_hist_value >= 5)
1078 filtered_quantized_color_gradients_ (col_index, row_index) =
static_cast<unsigned char> (0x1 << max_hist_index);
1080 filtered_quantized_color_gradients_ (col_index, row_index) = 0;
1087 template <
typename Po
intInT>
1093 const std::size_t width = mask_in.
getWidth ();
1094 const std::size_t height = mask_in.
getHeight ();
1096 mask_out.
resize (width, height);
1098 for (std::size_t row_index = 1; row_index < height-1; ++row_index)
1100 for (std::size_t col_index = 1; col_index < width-1; ++col_index)
1102 if (mask_in (col_index, row_index-1) == 0 ||
1103 mask_in (col_index-1, row_index) == 0 ||
1104 mask_in (col_index+1, row_index) == 0 ||
1105 mask_in (col_index, row_index+1) == 0)
1107 mask_out (col_index, row_index) = 0;
1111 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).
~ColorGradientModality()
Destructor.
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.
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 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.