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/features/linear_least_squares_normal.h>
91 resize (
const std::size_t width,
const std::size_t height,
const float value)
96 map_.resize (width*height, value);
104 operator() (
const std::size_t col_index,
const std::size_t row_index)
106 return map_[row_index * width_ + col_index];
114 operator() (
const std::size_t col_index,
const std::size_t row_index)
const
116 return map_[row_index * width_ + col_index];
121 std::size_t width_{0};
123 std::size_t height_{0};
125 std::vector<float> map_;
156 unsigned char *
lut{
nullptr};
173 initializeLUT (
const int range_x_arg,
const int range_y_arg,
const int range_z_arg)
191 constexpr
int nr_normals = 8;
194 constexpr
float normal0_angle = 40.0f * 3.14f / 180.0f;
195 ref_normals[0].x = std::cos (normal0_angle);
196 ref_normals[0].y = 0.0f;
197 ref_normals[0].z = -sinf (normal0_angle);
199 constexpr
float inv_nr_normals = 1.0f /
static_cast<float>(nr_normals);
200 for (
int normal_index = 1; normal_index < nr_normals; ++normal_index)
202 const float angle = 2.0f *
static_cast<float> (
M_PI * normal_index * inv_nr_normals);
204 ref_normals[normal_index].x = std::cos (angle) * ref_normals[0].x - sinf (angle) * ref_normals[0].y;
205 ref_normals[normal_index].y = sinf (angle) * ref_normals[0].x + std::cos (angle) * ref_normals[0].y;
206 ref_normals[normal_index].z = ref_normals[0].z;
210 for (
int normal_index = 0; normal_index < nr_normals; ++normal_index)
212 const float length = std::sqrt (ref_normals[normal_index].x * ref_normals[normal_index].x +
213 ref_normals[normal_index].y * ref_normals[normal_index].y +
214 ref_normals[normal_index].z * ref_normals[normal_index].z);
216 const float inv_length = 1.0f / length;
218 ref_normals[normal_index].x *= inv_length;
219 ref_normals[normal_index].y *= inv_length;
220 ref_normals[normal_index].z *= inv_length;
224 for (
int z_index = 0; z_index <
size_z; ++z_index)
226 for (
int y_index = 0; y_index <
size_y; ++y_index)
228 for (
int x_index = 0; x_index <
size_x; ++x_index)
231 static_cast<float> (y_index -
range_y/2),
232 static_cast<float> (z_index -
range_z));
233 const float length = std::sqrt (normal.x*normal.x + normal.y*normal.y + normal.z*normal.z);
234 const float inv_length = 1.0f / (length + 0.00001f);
236 normal.x *= inv_length;
237 normal.y *= inv_length;
238 normal.z *= inv_length;
240 float max_response = -1.0f;
243 for (
int normal_index = 0; normal_index < nr_normals; ++normal_index)
245 const float response = normal.x * ref_normals[normal_index].x +
246 normal.y * ref_normals[normal_index].y +
247 normal.z * ref_normals[normal_index].z;
249 const float abs_response = std::abs (response);
250 if (max_response < abs_response)
252 max_response = abs_response;
253 max_index = normal_index;
256 lut[z_index*
size_y*
size_x + y_index*
size_x + x_index] =
static_cast<unsigned char> (0x1 << max_index);
269 operator() (
const float x,
const float y,
const float z)
const
271 const auto x_index =
static_cast<std::size_t
> (x *
static_cast<float> (
offset_x) +
static_cast<float> (
offset_x));
272 const auto y_index =
static_cast<std::size_t
> (y *
static_cast<float> (
offset_y) +
static_cast<float> (
offset_y));
273 const auto z_index =
static_cast<std::size_t
> (z *
static_cast<float> (
range_z) +
static_cast<float> (
range_z));
295 template <
typename Po
intInT>
344 spreading_size_ = spreading_size;
353 variable_feature_nr_ = enabled;
360 return surface_normals_;
367 return surface_normals_;
374 return (filtered_quantized_surface_normals_);
381 return (spreaded_quantized_surface_normals_);
388 return (surface_normal_orientations_);
400 std::vector<QuantizedMultiModFeature> & features)
const override;
410 std::vector<QuantizedMultiModFeature> & features)
const override;
462 bool variable_feature_nr_{
false};
465 float feature_distance_threshold_{2.0f};
467 float min_distance_to_border_{2.0f};
470 QuantizedNormalLookUpTable normal_lookup_;
473 std::size_t spreading_size_{8};
492 template <
typename Po
intInT>
497 template <
typename Po
intInT>
501 template <
typename Po
intInT>
void
510 computeAndQuantizeSurfaceNormals2 ();
513 filterQuantizedSurfaceNormals ();
517 spreaded_quantized_surface_normals_,
522 template <
typename Po
intInT>
void
527 spreaded_quantized_surface_normals_,
532 template <
typename Po
intInT>
void
545 template <
typename Po
intInT>
void
557 const float bad_point = std::numeric_limits<float>::quiet_NaN ();
559 const int width = input_->width;
560 const int height = input_->height;
562 surface_normals_.resize (width*height);
563 surface_normals_.width = width;
564 surface_normals_.height = height;
565 surface_normals_.is_dense =
false;
567 quantized_surface_normals_.resize (width, height);
581 for (
int y = 0; y < height; ++y)
583 for (
int x = 0; x < width; ++x)
585 const int index = y * width + x;
587 const float px = (*input_)[index].x;
588 const float py = (*input_)[index].y;
589 const float pz = (*input_)[index].z;
591 if (std::isnan(px) || pz > 2.0f)
593 surface_normals_[index].normal_x = bad_point;
594 surface_normals_[index].normal_y = bad_point;
595 surface_normals_[index].normal_z = bad_point;
596 surface_normals_[index].curvature = bad_point;
598 quantized_surface_normals_ (x, y) = 0;
603 const int smoothingSizeInt = 5;
612 for (
int v = y - smoothingSizeInt; v <= y + smoothingSizeInt; v += smoothingSizeInt)
614 for (
int u = x - smoothingSizeInt; u <= x + smoothingSizeInt; u += smoothingSizeInt)
616 if (u < 0 || u >= width || v < 0 || v >= height)
continue;
618 const std::size_t index2 = v * width + u;
620 const float qx = (*input_)[index2].x;
621 const float qy = (*input_)[index2].y;
622 const float qz = (*input_)[index2].z;
624 if (std::isnan(qx))
continue;
626 const float delta = qz - pz;
627 const float i = qx - px;
628 const float j = qy - py;
630 const float f = std::abs(delta) < 0.05f ? 1.0f : 0.0f;
635 vecb0 += f * i * delta;
636 vecb1 += f * j * delta;
640 const float det = matA0 * matA3 - matA1 * matA1;
641 const float ddx = matA3 * vecb0 - matA1 * vecb1;
642 const float ddy = -matA1 * vecb0 + matA0 * vecb1;
644 const float nx = ddx;
645 const float ny = ddy;
646 const float nz = -det * pz;
648 const float length = nx * nx + ny * ny + nz * nz;
652 surface_normals_[index].normal_x = bad_point;
653 surface_normals_[index].normal_y = bad_point;
654 surface_normals_[index].normal_z = bad_point;
655 surface_normals_[index].curvature = bad_point;
657 quantized_surface_normals_ (x, y) = 0;
661 const float normInv = 1.0f / std::sqrt (length);
663 const float normal_x = nx * normInv;
664 const float normal_y = ny * normInv;
665 const float normal_z = nz * normInv;
667 surface_normals_[index].normal_x = normal_x;
668 surface_normals_[index].normal_y = normal_y;
669 surface_normals_[index].normal_z = normal_z;
670 surface_normals_[index].curvature = bad_point;
672 float angle = 11.25f + std::atan2 (normal_y, normal_x)*180.0f/3.14f;
674 if (angle < 0.0f) angle += 360.0f;
675 if (angle >= 360.0f) angle -= 360.0f;
677 int bin_index =
static_cast<int> (angle*8.0f/360.0f + 1);
678 bin_index = (bin_index < 1) ? 1 : (8 < bin_index) ? 8 : bin_index;
680 quantized_surface_normals_ (x, y) =
static_cast<unsigned char> (bin_index);
691 static void accumBilateral(
long delta,
long i,
long j,
long * A,
long * b,
int threshold)
693 long f = std::abs(delta) < threshold ? 1 : 0;
695 const long fi = f * i;
696 const long fj = f * j;
712 template <
typename Po
intInT>
void
715 const int width = input_->width;
716 const int height = input_->height;
718 auto * lp_depth =
new unsigned short[width*height]{};
719 auto * lp_normals =
new unsigned char[width*height]{};
721 surface_normal_orientations_.resize (width, height, 0.0f);
723 for (
int row_index = 0; row_index < height; ++row_index)
725 for (
int col_index = 0; col_index < width; ++col_index)
727 const float value = (*input_)[row_index*width + col_index].z;
728 if (std::isfinite (value))
730 lp_depth[row_index*width + col_index] =
static_cast<unsigned short> (value * 1000.0f);
734 lp_depth[row_index*width + col_index] = 0;
739 const int l_W = width;
740 const int l_H = height;
742 constexpr
int l_r = 5;
752 const int offsets_i[] = {-l_r, 0, l_r, -l_r, l_r, -l_r, 0, l_r};
753 const int offsets_j[] = {-l_r, -l_r, -l_r, 0, 0, l_r, l_r, l_r};
754 const int offsets[] = { offsets_i[0] + offsets_j[0] * l_W
755 , offsets_i[1] + offsets_j[1] * l_W
756 , offsets_i[2] + offsets_j[2] * l_W
757 , offsets_i[3] + offsets_j[3] * l_W
758 , offsets_i[4] + offsets_j[4] * l_W
759 , offsets_i[5] + offsets_j[5] * l_W
760 , offsets_i[6] + offsets_j[6] * l_W
761 , offsets_i[7] + offsets_j[7] * l_W };
767 constexpr
int difference_threshold = 50;
768 constexpr
int distance_threshold = 2000;
774 for (
int l_y = l_r; l_y < l_H - l_r - 1; ++l_y)
776 unsigned short * lp_line = lp_depth + (l_y * l_W + l_r);
777 unsigned char * lp_norm = lp_normals + (l_y * l_W + l_r);
779 for (
int l_x = l_r; l_x < l_W - l_r - 1; ++l_x)
781 long l_d = lp_line[0];
786 if (l_d < distance_threshold)
789 long l_A[4]; l_A[0] = l_A[1] = l_A[2] = l_A[3] = 0;
790 long l_b[2]; l_b[0] = l_b[1] = 0;
794 accumBilateral(lp_line[offsets[0]] - l_d, offsets_i[0], offsets_j[0], l_A, l_b, difference_threshold);
795 accumBilateral(lp_line[offsets[1]] - l_d, offsets_i[1], offsets_j[1], l_A, l_b, difference_threshold);
796 accumBilateral(lp_line[offsets[2]] - l_d, offsets_i[2], offsets_j[2], l_A, l_b, difference_threshold);
797 accumBilateral(lp_line[offsets[3]] - l_d, offsets_i[3], offsets_j[3], l_A, l_b, difference_threshold);
798 accumBilateral(lp_line[offsets[4]] - l_d, offsets_i[4], offsets_j[4], l_A, l_b, difference_threshold);
799 accumBilateral(lp_line[offsets[5]] - l_d, offsets_i[5], offsets_j[5], l_A, l_b, difference_threshold);
800 accumBilateral(lp_line[offsets[6]] - l_d, offsets_i[6], offsets_j[6], l_A, l_b, difference_threshold);
801 accumBilateral(lp_line[offsets[7]] - l_d, offsets_i[7], offsets_j[7], l_A, l_b, difference_threshold);
860 long l_det = l_A[0] * l_A[3] - l_A[1] * l_A[1];
861 long l_ddx = l_A[3] * l_b[0] - l_A[1] * l_b[1];
862 long l_ddy = -l_A[1] * l_b[0] + l_A[0] * l_b[1];
866 float l_nx =
static_cast<float>(1150 * l_ddx);
867 float l_ny =
static_cast<float>(1150 * l_ddy);
868 float l_nz =
static_cast<float>(-l_det * l_d);
882 float l_sqrt = std::sqrt (l_nx * l_nx + l_ny * l_ny + l_nz * l_nz);
886 float l_norminv = 1.0f / (l_sqrt);
892 float angle = 11.25f + std::atan2 (l_ny, l_nx) * 180.0f / 3.14f;
894 if (angle < 0.0f) angle += 360.0f;
895 if (angle >= 360.0f) angle -= 360.0f;
897 int bin_index =
static_cast<int> (angle*8.0f/360.0f);
899 surface_normal_orientations_ (l_x, l_y) = angle;
908 *lp_norm =
static_cast<unsigned char> (0x1 << bin_index);
925 unsigned char map[255]{};
936 quantized_surface_normals_.resize (width, height);
937 for (
int row_index = 0; row_index < height; ++row_index)
939 for (
int col_index = 0; col_index < width; ++col_index)
941 quantized_surface_normals_ (col_index, row_index) = map[lp_normals[row_index*width + col_index]];
951 template <
typename Po
intInT>
void
953 const std::size_t nr_features,
954 const std::size_t modality_index,
955 std::vector<QuantizedMultiModFeature> & features)
const
957 const std::size_t width = mask.
getWidth ();
958 const std::size_t height = mask.
getHeight ();
971 for (
auto &mask_map : mask_maps)
972 mask_map.
resize (width, height);
974 unsigned char map[255]{};
988 for (std::size_t row_index = 0; row_index < height; ++row_index)
990 for (std::size_t col_index = 0; col_index < width; ++col_index)
992 if (mask (col_index, row_index) != 0)
995 const unsigned char quantized_value = filtered_quantized_surface_normals_ (col_index, row_index);
997 if (quantized_value == 0)
999 const int dist_map_index = map[quantized_value];
1001 distance_map_indices (col_index, row_index) =
static_cast<unsigned char> (dist_map_index);
1003 mask_maps[dist_map_index] (col_index, row_index) = 255;
1009 for (
int map_index = 0; map_index < 8; ++map_index)
1010 computeDistanceMap (mask_maps[map_index], distance_maps[map_index]);
1013 computeDistanceMap (mask, mask_distance_maps);
1015 std::list<Candidate> list1;
1016 std::list<Candidate> list2;
1018 float weights[8] = {0,0,0,0,0,0,0,0};
1020 constexpr std::size_t off = 4;
1021 for (std::size_t row_index = off; row_index < height-off; ++row_index)
1023 for (std::size_t col_index = off; col_index < width-off; ++col_index)
1025 if (mask (col_index, row_index) != 0)
1028 const unsigned char quantized_value = filtered_quantized_surface_normals_ (col_index, row_index);
1034 if (quantized_value != 0)
1036 const int distance_map_index = map[quantized_value];
1039 const float distance = distance_maps[distance_map_index] (col_index, row_index);
1040 const float distance_to_border = mask_distance_maps (col_index, row_index);
1042 if (
distance >= feature_distance_threshold_ && distance_to_border >= min_distance_to_border_)
1047 candidate.
x = col_index;
1048 candidate.
y = row_index;
1049 candidate.
bin_index =
static_cast<unsigned char> (distance_map_index);
1051 list1.push_back (candidate);
1053 ++weights[distance_map_index];
1060 for (
auto iter = list1.begin (); iter != list1.end (); ++iter)
1061 iter->distance *= 1.0f / weights[iter->bin_index];
1065 if (variable_feature_nr_)
1067 int distance =
static_cast<int> (list1.size ());
1068 bool feature_selection_finished =
false;
1069 while (!feature_selection_finished)
1072 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
1074 bool candidate_accepted =
true;
1075 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
1077 const int dx =
static_cast<int> (iter1->x) -
static_cast<int> (iter2->x);
1078 const int dy =
static_cast<int> (iter1->y) -
static_cast<int> (iter2->y);
1079 const int tmp_distance = dx*dx + dy*dy;
1081 if (tmp_distance < sqr_distance)
1083 candidate_accepted =
false;
1089 float min_min_sqr_distance = std::numeric_limits<float>::max ();
1090 float max_min_sqr_distance = 0;
1091 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
1093 float min_sqr_distance = std::numeric_limits<float>::max ();
1094 for (
auto iter3 = list2.begin (); iter3 != list2.end (); ++iter3)
1099 const float dx =
static_cast<float> (iter2->x) -
static_cast<float> (iter3->x);
1100 const float dy =
static_cast<float> (iter2->y) -
static_cast<float> (iter3->y);
1102 const float sqr_distance = dx*dx + dy*dy;
1104 if (sqr_distance < min_sqr_distance)
1106 min_sqr_distance = sqr_distance;
1115 const float dx =
static_cast<float> (iter2->x) -
static_cast<float> (iter1->x);
1116 const float dy =
static_cast<float> (iter2->y) -
static_cast<float> (iter1->y);
1118 const float sqr_distance = dx*dx + dy*dy;
1120 if (sqr_distance < min_sqr_distance)
1122 min_sqr_distance = sqr_distance;
1126 if (min_sqr_distance < min_min_sqr_distance)
1127 min_min_sqr_distance = min_sqr_distance;
1128 if (min_sqr_distance > max_min_sqr_distance)
1129 max_min_sqr_distance = min_sqr_distance;
1134 if (candidate_accepted)
1140 if (min_min_sqr_distance < 50)
1142 feature_selection_finished =
true;
1146 list2.push_back (*iter1);
1160 if (list1.size () <= nr_features)
1162 features.reserve (list1.size ());
1163 for (
auto iter = list1.begin (); iter != list1.end (); ++iter)
1167 feature.
x =
static_cast<int> (iter->x);
1168 feature.
y =
static_cast<int> (iter->y);
1170 feature.
quantized_value = filtered_quantized_surface_normals_ (iter->x, iter->y);
1172 features.push_back (feature);
1178 int distance =
static_cast<int> (list1.size () / nr_features + 1);
1179 while (list2.size () != nr_features)
1182 for (
auto iter1 = list1.begin (); iter1 != list1.end (); ++iter1)
1184 bool candidate_accepted =
true;
1186 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
1188 const int dx =
static_cast<int> (iter1->x) -
static_cast<int> (iter2->x);
1189 const int dy =
static_cast<int> (iter1->y) -
static_cast<int> (iter2->y);
1190 const int tmp_distance = dx*dx + dy*dy;
1192 if (tmp_distance < sqr_distance)
1194 candidate_accepted =
false;
1199 if (candidate_accepted)
1200 list2.push_back (*iter1);
1202 if (list2.size () == nr_features)
break;
1208 for (
auto iter2 = list2.begin (); iter2 != list2.end (); ++iter2)
1212 feature.
x =
static_cast<int> (iter2->x);
1213 feature.
y =
static_cast<int> (iter2->y);
1215 feature.
quantized_value = filtered_quantized_surface_normals_ (iter2->x, iter2->y);
1217 features.push_back (feature);
1222 template <
typename Po
intInT>
void
1224 const MaskMap & mask,
const std::size_t,
const std::size_t modality_index,
1225 std::vector<QuantizedMultiModFeature> & features)
const
1227 const std::size_t width = mask.
getWidth ();
1228 const std::size_t height = mask.
getHeight ();
1241 for (
auto &mask_map : mask_maps)
1242 mask_map.
resize (width, height);
1244 unsigned char map[255]{};
1258 for (std::size_t row_index = 0; row_index < height; ++row_index)
1260 for (std::size_t col_index = 0; col_index < width; ++col_index)
1262 if (mask (col_index, row_index) != 0)
1265 const unsigned char quantized_value = filtered_quantized_surface_normals_ (col_index, row_index);
1267 if (quantized_value == 0)
1269 const int dist_map_index = map[quantized_value];
1271 distance_map_indices (col_index, row_index) =
static_cast<unsigned char> (dist_map_index);
1273 mask_maps[dist_map_index] (col_index, row_index) = 255;
1279 for (
int map_index = 0; map_index < 8; ++map_index)
1280 computeDistanceMap (mask_maps[map_index], distance_maps[map_index]);
1283 computeDistanceMap (mask, mask_distance_maps);
1285 std::list<Candidate> list1;
1286 std::list<Candidate> list2;
1288 float weights[8] = {0,0,0,0,0,0,0,0};
1290 constexpr std::size_t off = 4;
1291 for (std::size_t row_index = off; row_index < height-off; ++row_index)
1293 for (std::size_t col_index = off; col_index < width-off; ++col_index)
1295 if (mask (col_index, row_index) != 0)
1298 const unsigned char quantized_value = filtered_quantized_surface_normals_ (col_index, row_index);
1304 if (quantized_value != 0)
1306 const int distance_map_index = map[quantized_value];
1309 const float distance = distance_maps[distance_map_index] (col_index, row_index);
1310 const float distance_to_border = mask_distance_maps (col_index, row_index);
1312 if (
distance >= feature_distance_threshold_ && distance_to_border >= min_distance_to_border_)
1317 candidate.
x = col_index;
1318 candidate.
y = row_index;
1319 candidate.
bin_index =
static_cast<unsigned char> (distance_map_index);
1321 list1.push_back (candidate);
1323 ++weights[distance_map_index];
1330 for (
auto iter = list1.begin (); iter != list1.end (); ++iter)
1331 iter->distance *= 1.0f / weights[iter->bin_index];
1335 features.reserve (list1.size ());
1336 for (
auto iter = list1.begin (); iter != list1.end (); ++iter)
1340 feature.
x =
static_cast<int> (iter->x);
1341 feature.
y =
static_cast<int> (iter->y);
1343 feature.
quantized_value = filtered_quantized_surface_normals_ (iter->x, iter->y);
1345 features.push_back (feature);
1350 template <
typename Po
intInT>
void
1353 const std::size_t width = input_->width;
1354 const std::size_t height = input_->height;
1356 quantized_surface_normals_.resize (width, height);
1358 for (std::size_t row_index = 0; row_index < height; ++row_index)
1360 for (std::size_t col_index = 0; col_index < width; ++col_index)
1362 const float normal_x = surface_normals_ (col_index, row_index).normal_x;
1363 const float normal_y = surface_normals_ (col_index, row_index).normal_y;
1364 const float normal_z = surface_normals_ (col_index, row_index).normal_z;
1366 if (std::isnan(normal_x) || std::isnan(normal_y) || std::isnan(normal_z) || normal_z > 0 || (normal_x == 0 && normal_y == 0))
1368 quantized_surface_normals_ (col_index, row_index) = 0;
1375 float angle = 11.25f + std::atan2 (normal_y, normal_x)*180.0f/3.14f;
1377 if (angle < 0.0f) angle += 360.0f;
1378 if (angle >= 360.0f) angle -= 360.0f;
1380 int bin_index =
static_cast<int> (angle*8.0f/360.0f + 1);
1381 bin_index = (bin_index < 1) ? 1 : (8 < bin_index) ? 8 : bin_index;
1384 quantized_surface_normals_ (col_index, row_index) =
static_cast<unsigned char> (bin_index);
1392 template <
typename Po
intInT>
void
1395 const int width = input_->width;
1396 const int height = input_->height;
1398 filtered_quantized_surface_normals_.resize (width, height);
1455 for (
int row_index = 2; row_index < height-2; ++row_index)
1457 for (
int col_index = 2; col_index < width-2; ++col_index)
1459 unsigned char histogram[9] = {0,0,0,0,0,0,0,0,0};
1481 unsigned char * dataPtr = quantized_surface_normals_.getData () + (row_index-2)*width+col_index-2;
1482 ++histogram[dataPtr[0]];
1483 ++histogram[dataPtr[1]];
1484 ++histogram[dataPtr[2]];
1485 ++histogram[dataPtr[3]];
1486 ++histogram[dataPtr[4]];
1489 unsigned char * dataPtr = quantized_surface_normals_.getData () + (row_index-1)*width+col_index-2;
1490 ++histogram[dataPtr[0]];
1491 ++histogram[dataPtr[1]];
1492 ++histogram[dataPtr[2]];
1493 ++histogram[dataPtr[3]];
1494 ++histogram[dataPtr[4]];
1497 unsigned char * dataPtr = quantized_surface_normals_.getData () + (row_index)*width+col_index-2;
1498 ++histogram[dataPtr[0]];
1499 ++histogram[dataPtr[1]];
1500 ++histogram[dataPtr[2]];
1501 ++histogram[dataPtr[3]];
1502 ++histogram[dataPtr[4]];
1505 unsigned char * dataPtr = quantized_surface_normals_.getData () + (row_index+1)*width+col_index-2;
1506 ++histogram[dataPtr[0]];
1507 ++histogram[dataPtr[1]];
1508 ++histogram[dataPtr[2]];
1509 ++histogram[dataPtr[3]];
1510 ++histogram[dataPtr[4]];
1513 unsigned char * dataPtr = quantized_surface_normals_.getData () + (row_index+2)*width+col_index-2;
1514 ++histogram[dataPtr[0]];
1515 ++histogram[dataPtr[1]];
1516 ++histogram[dataPtr[2]];
1517 ++histogram[dataPtr[3]];
1518 ++histogram[dataPtr[4]];
1522 unsigned char max_hist_value = 0;
1523 int max_hist_index = -1;
1525 if (max_hist_value < histogram[1]) {max_hist_index = 0; max_hist_value = histogram[1];}
1526 if (max_hist_value < histogram[2]) {max_hist_index = 1; max_hist_value = histogram[2];}
1527 if (max_hist_value < histogram[3]) {max_hist_index = 2; max_hist_value = histogram[3];}
1528 if (max_hist_value < histogram[4]) {max_hist_index = 3; max_hist_value = histogram[4];}
1529 if (max_hist_value < histogram[5]) {max_hist_index = 4; max_hist_value = histogram[5];}
1530 if (max_hist_value < histogram[6]) {max_hist_index = 5; max_hist_value = histogram[6];}
1531 if (max_hist_value < histogram[7]) {max_hist_index = 6; max_hist_value = histogram[7];}
1532 if (max_hist_value < histogram[8]) {max_hist_index = 7; max_hist_value = histogram[8];}
1534 if (max_hist_index != -1 && max_hist_value >= 1)
1536 filtered_quantized_surface_normals_ (col_index, row_index) =
static_cast<unsigned char> (0x1 << max_hist_index);
1540 filtered_quantized_surface_normals_ (col_index, row_index) = 0;
1564 template <
typename Po
intInT>
void
1567 const std::size_t width = input.
getWidth ();
1568 const std::size_t height = input.
getHeight ();
1570 output.
resize (width, height);
1574 const unsigned char * mask_map = input.
getData ();
1575 float * distance_map = output.
getData ();
1576 for (std::size_t index = 0; index < width*height; ++index)
1578 if (mask_map[index] == 0)
1579 distance_map[index] = 0.0f;
1581 distance_map[index] =
static_cast<float> (width + height);
1585 float * previous_row = distance_map;
1586 float * current_row = previous_row + width;
1587 for (std::size_t ri = 1; ri < height; ++ri)
1589 for (std::size_t ci = 1; ci < width; ++ci)
1591 const float up_left = previous_row [ci - 1] + 1.4f;
1592 const float up = previous_row [ci] + 1.0f;
1593 const float up_right = previous_row [ci + 1] + 1.4f;
1594 const float left = current_row [ci - 1] + 1.0f;
1595 const float center = current_row [ci];
1597 const float min_value = std::min (std::min (up_left, up), std::min (left, up_right));
1599 if (min_value < center)
1600 current_row[ci] = min_value;
1602 previous_row = current_row;
1603 current_row += width;
1607 float * next_row = distance_map + width * (height - 1);
1608 current_row = next_row - width;
1609 for (
int ri =
static_cast<int> (height)-2; ri >= 0; --ri)
1611 for (
int ci =
static_cast<int> (width)-2; ci >= 0; --ci)
1613 const float lower_left = next_row [ci - 1] + 1.4f;
1614 const float lower = next_row [ci] + 1.0f;
1615 const float lower_right = next_row [ci + 1] + 1.4f;
1616 const float right = current_row [ci + 1] + 1.0f;
1617 const float center = current_row [ci];
1619 const float min_value = std::min (std::min (lower_left, lower), std::min (right, lower_right));
1621 if (min_value < center)
1622 current_row[ci] = min_value;
1624 next_row = current_row;
1625 current_row -= width;
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.
void compute(PointCloudOut &output)
Base method for feature estimation for all points given in <setInputCloud (), setIndices ()> using th...
Surface normal estimation on dense data using a least-squares estimation based on a first-order Taylo...
void setNormalSmoothingSize(float normal_smoothing_size)
Set the normal smoothing size.
void setInputCloud(const typename PointCloudIn::ConstPtr &cloud) override
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method)
void setMaxDepthChangeFactor(float max_depth_change_factor)
The depth change threshold for computing object borders.
void setDepthDependentSmoothing(bool use_depth_dependent_smoothing)
Set whether to use depth depending smoothing or not.
std::size_t getWidth() const
unsigned char * getData()
void resize(std::size_t width, std::size_t height)
std::size_t getHeight() const
PointCloudConstPtr input_
The input point cloud dataset.
std::vector< PointT, Eigen::aligned_allocator< PointT > > VectorType
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)
Modality based on surface normals.
void computeSurfaceNormals()
Computes the surface normals from the input cloud.
void computeAndQuantizeSurfaceNormals()
Computes and quantizes the surface normals.
void setSpreadingSize(const std::size_t spreading_size)
Sets the spreading size.
const pcl::PointCloud< pcl::Normal > & getSurfaceNormals() const
Returns the surface normals.
void computeAndQuantizeSurfaceNormals2()
Computes and quantizes the surface normals.
virtual void processInputData()
Processes the input data (smoothing, computing gradients, quantizing, filtering, spreading).
~SurfaceNormalModality() override
Destructor.
virtual void processInputDataFromFiltered()
Processes the input data assuming that everything up to filtering is already done/available (so only ...
QuantizedMap & getSpreadedQuantizedMap() override
Returns a reference to the internal spread quantized map.
void quantizeSurfaceNormals()
Quantizes the surface normals.
void setInputCloud(const typename PointCloudIn::ConstPtr &cloud) override
Provide a pointer to the input dataset (overwrites the PCLBase::setInputCloud method)
QuantizedMap & getQuantizedMap() override
Returns a reference to the internal quantized map.
void extractAllFeatures(const MaskMap &mask, std::size_t nr_features, std::size_t modality_index, std::vector< QuantizedMultiModFeature > &features) const override
Extracts all possible features from the modality within the specified mask.
void computeDistanceMap(const MaskMap &input, DistanceMap &output) const
Computes a distance map from the supplied input mask.
pcl::PointCloud< pcl::Normal > & getSurfaceNormals()
Returns the surface normals.
LINEMOD_OrientationMap & getOrientationMap()
Returns a reference to the orientation map.
SurfaceNormalModality()
Constructor.
void setVariableFeatureNr(const bool enabled)
Enables/disables the use of extracting a variable number of features.
void filterQuantizedSurfaceNormals()
Filters the quantized surface normals.
void extractFeatures(const MaskMap &mask, std::size_t nr_features, std::size_t modality_index, std::vector< QuantizedMultiModFeature > &features) const override
Extracts features from this modality within the specified mask.
Defines all the PCL implemented PointT point type structures.
float distance(const PointT &p1, const PointT &p2)
Map that stores orientations.
LINEMOD_OrientationMap()=default
Constructor.
std::size_t getWidth() const
Returns the width of the modality data map.
std::size_t getHeight() const
Returns the height of the modality data map.
~LINEMOD_OrientationMap()=default
Destructor.
void resize(const std::size_t width, const std::size_t height, const float value)
Resizes the map to the specific width and height and initializes all new elements with the specified ...
A point structure representing normal coordinates and the surface curvature estimate.
A point structure representing Euclidean xyz coordinates.
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.
Look-up-table for fast surface normal quantization.
QuantizedNormalLookUpTable()=default
Constructor.
int size_y
The size of the LUT in y-direction.
void initializeLUT(const int range_x_arg, const int range_y_arg, const int range_z_arg)
Initializes the LUT.
int size_x
The size of the LUT in x-direction.
unsigned char operator()(const float x, const float y, const float z) const
Operator to access an element in the LUT.
~QuantizedNormalLookUpTable()
Destructor.
int range_y
The range of the LUT in y-direction.
int offset_x
The offset in x-direction.
unsigned char * lut
The LUT data.
int offset_z
The offset in z-direction.
int range_z
The range of the LUT in z-direction.
int size_z
The size of the LUT in z-direction.
int range_x
The range of the LUT in x-direction.
int offset_y
The offset in y-direction.
Candidate for a feature (used in feature extraction methods).
float distance
Distance to the next different quantized value.
Candidate()=default
Constructor.
std::size_t x
x-position of the feature.
std::size_t y
y-position of the feature.
bool operator<(const Candidate &rhs) const
Compares two candidates based on their distance to the next different quantized value.
unsigned char bin_index
Quantized value.