40 #ifndef PCL_FEATURES_IMPL_SHOT_H_
41 #define PCL_FEATURES_IMPL_SHOT_H_
43 #include <pcl/features/shot.h>
44 #include <pcl/features/shot_lrf.h>
46 #include <pcl/common/colors.h>
49 #define PST_PI 3.1415926535897932384626433832795
50 #define PST_RAD_45 0.78539816339744830961566084581988
51 #define PST_RAD_90 1.5707963267948966192313216916398
52 #define PST_RAD_135 2.3561944901923449288469825374596
53 #define PST_RAD_180 PST_PI
54 #define PST_RAD_360 6.283185307179586476925286766558
55 #define PST_RAD_PI_7_8 2.7488935718910690836548129603691
57 const double zeroDoubleEps15 = 1E-15;
58 const float zeroFloatEps8 = 1E-8f;
69 areEquals (
double val1,
double val2,
double zeroDoubleEps = zeroDoubleEps15)
71 return (std::abs (val1 - val2)<zeroDoubleEps);
83 areEquals (
float val1,
float val2,
float zeroFloatEps = zeroFloatEps8)
85 return (std::fabs (val1 - val2)<zeroFloatEps);
89 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
90 std::array<float, 256>
94 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
95 std::array<float, 4000>
99 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
101 unsigned char B,
float &L,
float &A,
104 float fr = sRGB_LUT[R];
105 float fg = sRGB_LUT[G];
106 float fb = sRGB_LUT[
B];
109 const float x = fr * 0.412453f + fg * 0.357580f + fb * 0.180423f;
110 const float y = fr * 0.212671f + fg * 0.715160f + fb * 0.072169f;
111 const float z = fr * 0.019334f + fg * 0.119193f + fb * 0.950227f;
113 float vx = x / 0.95047f;
115 float vz = z / 1.08883f;
117 vx = sXYZ_LUT[
static_cast<int>(vx*4000)];
118 vy = sXYZ_LUT[
static_cast<int>(vy*4000)];
119 vz = sXYZ_LUT[
static_cast<int>(vz*4000)];
121 L = 116.0f * vy - 16.0f;
125 A = 500.0f * (vx - vy);
131 B2 = 200.0f * (vy - vz);
139 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
bool
144 PCL_ERROR (
"[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
149 if (this->getKSearch () != 0)
152 "[pcl::%s::initCompute] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n",
153 getClassName().c_str ());
159 lrf_estimator->setRadiusSearch ((lrf_radius_ > 0 ? lrf_radius_ : search_radius_));
160 lrf_estimator->setInputCloud (input_);
161 lrf_estimator->setIndices (indices_);
163 lrf_estimator->setSearchSurface(surface_);
167 PCL_ERROR (
"[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
175 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
179 std::vector<double> &bin_distance_shape)
181 bin_distance_shape.resize (indices.size ());
183 const PointRFT& current_frame = (*frames_)[index];
187 Eigen::Vector4f current_frame_z (current_frame.z_axis[0], current_frame.z_axis[1], current_frame.z_axis[2], 0);
189 unsigned nan_counter = 0;
190 for (std::size_t i_idx = 0; i_idx < indices.size (); ++i_idx)
193 const Eigen::Vector4f& normal_vec = (*normals_)[indices[i_idx]].getNormalVector4fMap ();
194 if (!std::isfinite (normal_vec[0]) ||
195 !std::isfinite (normal_vec[1]) ||
196 !std::isfinite (normal_vec[2]))
198 bin_distance_shape[i_idx] = std::numeric_limits<double>::quiet_NaN ();
203 double cosineDesc = normal_vec.dot (current_frame_z);
205 if (cosineDesc > 1.0)
207 if (cosineDesc < - 1.0)
210 bin_distance_shape[i_idx] = ((1.0 + cosineDesc) * nr_shape_bins_) / 2;
214 PCL_WARN (
"[pcl::%s::createBinDistanceShape] Point %d has %d (%f%%) NaN normals in its neighbourhood\n",
215 getClassName ().c_str (), index, nan_counter, (
static_cast<float>(nan_counter)*100.f/
static_cast<float>(indices.size ())));
219 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
221 Eigen::VectorXf &shot,
int desc_length)
228 for (
int j = 0; j < desc_length; j++)
229 acc_norm += shot[j] * shot[j];
230 acc_norm = sqrt (acc_norm);
231 for (
int j = 0; j < desc_length; j++)
232 shot[j] /=
static_cast<float> (acc_norm);
236 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
239 const std::vector<float> &sqr_dists,
241 std::vector<double> &binDistance,
243 Eigen::VectorXf &shot)
245 const Eigen::Vector4f& central_point = (*input_)[(*indices_)[index]].getVector4fMap ();
246 const PointRFT& current_frame = (*frames_)[index];
248 Eigen::Vector4f current_frame_x (current_frame.x_axis[0], current_frame.x_axis[1], current_frame.x_axis[2], 0);
249 Eigen::Vector4f current_frame_y (current_frame.y_axis[0], current_frame.y_axis[1], current_frame.y_axis[2], 0);
250 Eigen::Vector4f current_frame_z (current_frame.z_axis[0], current_frame.z_axis[1], current_frame.z_axis[2], 0);
252 for (std::size_t i_idx = 0; i_idx < indices.size (); ++i_idx)
254 if (!std::isfinite(binDistance[i_idx]))
257 Eigen::Vector4f delta = (*surface_)[indices[i_idx]].getVector4fMap () - central_point;
261 double distance = sqrt (sqr_dists[i_idx]);
266 double xInFeatRef = delta.dot (current_frame_x);
267 double yInFeatRef = delta.dot (current_frame_y);
268 double zInFeatRef = delta.dot (current_frame_z);
271 if (std::abs (yInFeatRef) < 1E-30)
273 if (std::abs (xInFeatRef) < 1E-30)
275 if (std::abs (zInFeatRef) < 1E-30)
279 unsigned char bit4 = ((yInFeatRef > 0) || ((yInFeatRef == 0.0) && (xInFeatRef < 0))) ? 1 : 0;
280 auto bit3 =
static_cast<unsigned char> (((xInFeatRef > 0) || ((xInFeatRef == 0.0) && (yInFeatRef > 0))) ? !bit4 : bit4);
282 assert (bit3 == 0 || bit3 == 1);
284 int desc_index = (bit4<<3) + (bit3<<2);
286 desc_index = desc_index << 1;
288 if ((xInFeatRef * yInFeatRef > 0) || (xInFeatRef == 0.0))
289 desc_index += (std::abs (xInFeatRef) >= std::abs (yInFeatRef)) ? 0 : 4;
291 desc_index += (std::abs (xInFeatRef) > std::abs (yInFeatRef)) ? 4 : 0;
293 desc_index += zInFeatRef > 0 ? 1 : 0;
296 desc_index += (
distance > radius1_2_) ? 2 : 0;
298 int step_index =
static_cast<int>(std::floor (binDistance[i_idx] +0.5));
299 int volume_index = desc_index * (nr_bins+1);
302 binDistance[i_idx] -= step_index;
303 double intWeight = (1- std::abs (binDistance[i_idx]));
305 if (binDistance[i_idx] > 0)
306 shot[volume_index + ((step_index+1) % nr_bins)] +=
static_cast<float> (binDistance[i_idx]);
308 shot[volume_index + ((step_index - 1 + nr_bins) % nr_bins)] += -
static_cast<float> (binDistance[i_idx]);
314 double radiusDistance = (
distance - radius3_4_) / radius1_2_;
317 intWeight += 1 - radiusDistance;
320 intWeight += 1 + radiusDistance;
321 shot[(desc_index - 2) * (nr_bins+1) + step_index] -=
static_cast<float> (radiusDistance);
326 double radiusDistance = (
distance - radius1_4_) / radius1_2_;
329 intWeight += 1 + radiusDistance;
332 intWeight += 1 - radiusDistance;
333 shot[(desc_index + 2) * (nr_bins+1) + step_index] +=
static_cast<float> (radiusDistance);
338 double inclinationCos = zInFeatRef /
distance;
339 if (inclinationCos < - 1.0)
340 inclinationCos = - 1.0;
341 if (inclinationCos > 1.0)
342 inclinationCos = 1.0;
344 double inclination = std::acos (inclinationCos);
346 assert (inclination >= 0.0 && inclination <= PST_RAD_180);
348 if (inclination > PST_RAD_90 || (std::abs (inclination - PST_RAD_90) < 1e-30 && zInFeatRef <= 0))
350 double inclinationDistance = (inclination - PST_RAD_135) / PST_RAD_90;
351 if (inclination > PST_RAD_135)
352 intWeight += 1 - inclinationDistance;
355 intWeight += 1 + inclinationDistance;
356 assert ((desc_index + 1) * (nr_bins+1) + step_index >= 0 && (desc_index + 1) * (nr_bins+1) + step_index < descLength_);
357 shot[(desc_index + 1) * (nr_bins+1) + step_index] -=
static_cast<float> (inclinationDistance);
362 double inclinationDistance = (inclination - PST_RAD_45) / PST_RAD_90;
363 if (inclination < PST_RAD_45)
364 intWeight += 1 + inclinationDistance;
367 intWeight += 1 - inclinationDistance;
368 assert ((desc_index - 1) * (nr_bins+1) + step_index >= 0 && (desc_index - 1) * (nr_bins+1) + step_index < descLength_);
369 shot[(desc_index - 1) * (nr_bins+1) + step_index] +=
static_cast<float> (inclinationDistance);
373 if (yInFeatRef != 0.0 || xInFeatRef != 0.0)
376 double azimuth = std::atan2 (yInFeatRef, xInFeatRef);
378 int sel = desc_index >> 2;
379 double angularSectorSpan = PST_RAD_45;
380 double angularSectorStart = - PST_RAD_PI_7_8;
382 double azimuthDistance = (azimuth - (angularSectorStart + angularSectorSpan*sel)) / angularSectorSpan;
384 assert ((azimuthDistance < 0.5 || areEquals (azimuthDistance, 0.5)) && (azimuthDistance > - 0.5 || areEquals (azimuthDistance, - 0.5)));
386 azimuthDistance = (std::max)(- 0.5, std::min (azimuthDistance, 0.5));
388 if (azimuthDistance > 0)
390 intWeight += 1 - azimuthDistance;
391 int interp_index = (desc_index + 4) % maxAngularSectors_;
392 assert (interp_index * (nr_bins+1) + step_index >= 0 && interp_index * (nr_bins+1) + step_index < descLength_);
393 shot[interp_index * (nr_bins+1) + step_index] +=
static_cast<float> (azimuthDistance);
397 int interp_index = (desc_index - 4 + maxAngularSectors_) % maxAngularSectors_;
398 assert (interp_index * (nr_bins+1) + step_index >= 0 && interp_index * (nr_bins+1) + step_index < descLength_);
399 intWeight += 1 + azimuthDistance;
400 shot[interp_index * (nr_bins+1) + step_index] -=
static_cast<float> (azimuthDistance);
405 assert (volume_index + step_index >= 0 && volume_index + step_index < descLength_);
406 shot[volume_index + step_index] +=
static_cast<float> (intWeight);
411 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
414 const std::vector<float> &sqr_dists,
416 std::vector<double> &binDistanceShape,
417 std::vector<double> &binDistanceColor,
418 const int nr_bins_shape,
419 const int nr_bins_color,
420 Eigen::VectorXf &shot)
422 const Eigen::Vector4f ¢ral_point = (*input_)[(*indices_)[index]].getVector4fMap ();
423 const PointRFT& current_frame = (*frames_)[index];
425 int shapeToColorStride = nr_grid_sector_*(nr_bins_shape+1);
427 Eigen::Vector4f current_frame_x (current_frame.x_axis[0], current_frame.x_axis[1], current_frame.x_axis[2], 0);
428 Eigen::Vector4f current_frame_y (current_frame.y_axis[0], current_frame.y_axis[1], current_frame.y_axis[2], 0);
429 Eigen::Vector4f current_frame_z (current_frame.z_axis[0], current_frame.z_axis[1], current_frame.z_axis[2], 0);
431 for (std::size_t i_idx = 0; i_idx < indices.size (); ++i_idx)
433 if (!std::isfinite(binDistanceShape[i_idx]))
436 Eigen::Vector4f delta = (*surface_)[indices[i_idx]].getVector4fMap () - central_point;
440 double distance = sqrt (sqr_dists[i_idx]);
445 double xInFeatRef = delta.dot (current_frame_x);
446 double yInFeatRef = delta.dot (current_frame_y);
447 double zInFeatRef = delta.dot (current_frame_z);
450 if (std::abs (yInFeatRef) < 1E-30)
452 if (std::abs (xInFeatRef) < 1E-30)
454 if (std::abs (zInFeatRef) < 1E-30)
457 unsigned char bit4 = ((yInFeatRef > 0) || ((yInFeatRef == 0.0) && (xInFeatRef < 0))) ? 1 : 0;
458 auto bit3 =
static_cast<unsigned char> (((xInFeatRef > 0) || ((xInFeatRef == 0.0) && (yInFeatRef > 0))) ? !bit4 : bit4);
460 assert (bit3 == 0 || bit3 == 1);
462 int desc_index = (bit4<<3) + (bit3<<2);
464 desc_index = desc_index << 1;
466 if ((xInFeatRef * yInFeatRef > 0) || (xInFeatRef == 0.0))
467 desc_index += (std::abs (xInFeatRef) >= std::abs (yInFeatRef)) ? 0 : 4;
469 desc_index += (std::abs (xInFeatRef) > std::abs (yInFeatRef)) ? 4 : 0;
471 desc_index += zInFeatRef > 0 ? 1 : 0;
474 desc_index += (
distance > radius1_2_) ? 2 : 0;
476 int step_index_shape =
static_cast<int>(std::floor (binDistanceShape[i_idx] +0.5));
477 int step_index_color =
static_cast<int>(std::floor (binDistanceColor[i_idx] +0.5));
479 int volume_index_shape = desc_index * (nr_bins_shape+1);
480 int volume_index_color = shapeToColorStride + desc_index * (nr_bins_color+1);
483 binDistanceShape[i_idx] -= step_index_shape;
484 binDistanceColor[i_idx] -= step_index_color;
486 double intWeightShape = (1- std::abs (binDistanceShape[i_idx]));
487 double intWeightColor = (1- std::abs (binDistanceColor[i_idx]));
489 if (binDistanceShape[i_idx] > 0)
490 shot[volume_index_shape + ((step_index_shape + 1) % nr_bins_shape)] +=
static_cast<float> (binDistanceShape[i_idx]);
492 shot[volume_index_shape + ((step_index_shape - 1 + nr_bins_shape) % nr_bins_shape)] -=
static_cast<float> (binDistanceShape[i_idx]);
494 if (binDistanceColor[i_idx] > 0)
495 shot[volume_index_color + ((step_index_color+1) % nr_bins_color)] +=
static_cast<float> (binDistanceColor[i_idx]);
497 shot[volume_index_color + ((step_index_color - 1 + nr_bins_color) % nr_bins_color)] -=
static_cast<float> (binDistanceColor[i_idx]);
503 double radiusDistance = (
distance - radius3_4_) / radius1_2_;
507 intWeightShape += 1 - radiusDistance;
508 intWeightColor += 1 - radiusDistance;
512 intWeightShape += 1 + radiusDistance;
513 intWeightColor += 1 + radiusDistance;
514 shot[(desc_index - 2) * (nr_bins_shape+1) + step_index_shape] -=
static_cast<float> (radiusDistance);
515 shot[shapeToColorStride + (desc_index - 2) * (nr_bins_color+1) + step_index_color] -=
static_cast<float> (radiusDistance);
520 double radiusDistance = (
distance - radius1_4_) / radius1_2_;
524 intWeightShape += 1 + radiusDistance;
525 intWeightColor += 1 + radiusDistance;
529 intWeightShape += 1 - radiusDistance;
530 intWeightColor += 1 - radiusDistance;
531 shot[(desc_index + 2) * (nr_bins_shape+1) + step_index_shape] +=
static_cast<float> (radiusDistance);
532 shot[shapeToColorStride + (desc_index + 2) * (nr_bins_color+1) + step_index_color] +=
static_cast<float> (radiusDistance);
537 double inclinationCos = zInFeatRef /
distance;
538 if (inclinationCos < - 1.0)
539 inclinationCos = - 1.0;
540 if (inclinationCos > 1.0)
541 inclinationCos = 1.0;
543 double inclination = std::acos (inclinationCos);
545 assert (inclination >= 0.0 && inclination <= PST_RAD_180);
547 if (inclination > PST_RAD_90 || (std::abs (inclination - PST_RAD_90) < 1e-30 && zInFeatRef <= 0))
549 double inclinationDistance = (inclination - PST_RAD_135) / PST_RAD_90;
550 if (inclination > PST_RAD_135)
552 intWeightShape += 1 - inclinationDistance;
553 intWeightColor += 1 - inclinationDistance;
557 intWeightShape += 1 + inclinationDistance;
558 intWeightColor += 1 + inclinationDistance;
559 assert ((desc_index + 1) * (nr_bins_shape+1) + step_index_shape >= 0 && (desc_index + 1) * (nr_bins_shape+1) + step_index_shape < descLength_);
560 assert (shapeToColorStride + (desc_index + 1) * (nr_bins_color+ 1) + step_index_color >= 0 && shapeToColorStride + (desc_index + 1) * (nr_bins_color+1) + step_index_color < descLength_);
561 shot[(desc_index + 1) * (nr_bins_shape+1) + step_index_shape] -=
static_cast<float> (inclinationDistance);
562 shot[shapeToColorStride + (desc_index + 1) * (nr_bins_color+1) + step_index_color] -=
static_cast<float> (inclinationDistance);
567 double inclinationDistance = (inclination - PST_RAD_45) / PST_RAD_90;
568 if (inclination < PST_RAD_45)
570 intWeightShape += 1 + inclinationDistance;
571 intWeightColor += 1 + inclinationDistance;
575 intWeightShape += 1 - inclinationDistance;
576 intWeightColor += 1 - inclinationDistance;
577 assert ((desc_index - 1) * (nr_bins_shape+1) + step_index_shape >= 0 && (desc_index - 1) * (nr_bins_shape+1) + step_index_shape < descLength_);
578 assert (shapeToColorStride + (desc_index - 1) * (nr_bins_color+ 1) + step_index_color >= 0 && shapeToColorStride + (desc_index - 1) * (nr_bins_color+1) + step_index_color < descLength_);
579 shot[(desc_index - 1) * (nr_bins_shape+1) + step_index_shape] +=
static_cast<float> (inclinationDistance);
580 shot[shapeToColorStride + (desc_index - 1) * (nr_bins_color+1) + step_index_color] +=
static_cast<float> (inclinationDistance);
584 if (yInFeatRef != 0.0 || xInFeatRef != 0.0)
587 double azimuth = std::atan2 (yInFeatRef, xInFeatRef);
589 int sel = desc_index >> 2;
590 double angularSectorSpan = PST_RAD_45;
591 double angularSectorStart = - PST_RAD_PI_7_8;
593 double azimuthDistance = (azimuth - (angularSectorStart + angularSectorSpan*sel)) / angularSectorSpan;
594 assert ((azimuthDistance < 0.5 || areEquals (azimuthDistance, 0.5)) && (azimuthDistance > - 0.5 || areEquals (azimuthDistance, - 0.5)));
595 azimuthDistance = (std::max)(- 0.5, std::min (azimuthDistance, 0.5));
597 if (azimuthDistance > 0)
599 intWeightShape += 1 - azimuthDistance;
600 intWeightColor += 1 - azimuthDistance;
601 int interp_index = (desc_index + 4) % maxAngularSectors_;
602 assert (interp_index * (nr_bins_shape+1) + step_index_shape >= 0 && interp_index * (nr_bins_shape+1) + step_index_shape < descLength_);
603 assert (shapeToColorStride + interp_index * (nr_bins_color+1) + step_index_color >= 0 && shapeToColorStride + interp_index * (nr_bins_color+1) + step_index_color < descLength_);
604 shot[interp_index * (nr_bins_shape+1) + step_index_shape] +=
static_cast<float> (azimuthDistance);
605 shot[shapeToColorStride + interp_index * (nr_bins_color+1) + step_index_color] +=
static_cast<float> (azimuthDistance);
609 int interp_index = (desc_index - 4 + maxAngularSectors_) % maxAngularSectors_;
610 intWeightShape += 1 + azimuthDistance;
611 intWeightColor += 1 + azimuthDistance;
612 assert (interp_index * (nr_bins_shape+1) + step_index_shape >= 0 && interp_index * (nr_bins_shape+1) + step_index_shape < descLength_);
613 assert (shapeToColorStride + interp_index * (nr_bins_color+1) + step_index_color >= 0 && shapeToColorStride + interp_index * (nr_bins_color+1) + step_index_color < descLength_);
614 shot[interp_index * (nr_bins_shape+1) + step_index_shape] -=
static_cast<float> (azimuthDistance);
615 shot[shapeToColorStride + interp_index * (nr_bins_color+1) + step_index_color] -=
static_cast<float> (azimuthDistance);
619 assert (volume_index_shape + step_index_shape >= 0 && volume_index_shape + step_index_shape < descLength_);
620 assert (volume_index_color + step_index_color >= 0 && volume_index_color + step_index_color < descLength_);
621 shot[volume_index_shape + step_index_shape] +=
static_cast<float> (intWeightShape);
622 shot[volume_index_color + step_index_color] +=
static_cast<float> (intWeightColor);
627 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
629 const int index,
const pcl::Indices &indices,
const std::vector<float> &sqr_dists, Eigen::VectorXf &shot)
633 const auto nNeighbors = indices.size ();
637 PCL_WARN (
"[pcl::%s::computePointSHOT] Warning! Neighborhood has less than 5 vertexes. Aborting description of point with index %d\n",
638 getClassName ().c_str (), (*indices_)[index]);
640 shot.setConstant(descLength_, 1, std::numeric_limits<float>::quiet_NaN () );
646 std::vector<double> binDistanceShape;
647 if (b_describe_shape_)
649 this->createBinDistanceShape (index, indices, binDistanceShape);
653 std::vector<double> binDistanceColor;
654 if (b_describe_color_)
656 binDistanceColor.reserve (nNeighbors);
661 unsigned char redRef = (*input_)[(*indices_)[index]].r;
662 unsigned char greenRef = (*input_)[(*indices_)[index]].g;
663 unsigned char blueRef = (*input_)[(*indices_)[index]].b;
665 float LRef, aRef, bRef;
667 RGB2CIELAB (redRef, greenRef, blueRef, LRef, aRef, bRef);
672 for (
const auto& idx: indices)
674 unsigned char red = (*surface_)[idx].r;
675 unsigned char green = (*surface_)[idx].g;
676 unsigned char blue = (*surface_)[idx].b;
680 RGB2CIELAB (red, green, blue, L, a, b);
685 double colorDistance = (std::fabs (LRef - L) + ((std::fabs (aRef - a) + std::fabs (bRef - b)) / 2)) /3;
687 if (colorDistance > 1.0)
689 if (colorDistance < 0.0)
692 binDistanceColor.push_back (colorDistance * nr_color_bins_);
698 if (b_describe_shape_ && b_describe_color_)
699 interpolateDoubleChannel (indices, sqr_dists, index, binDistanceShape, binDistanceColor,
700 nr_shape_bins_, nr_color_bins_,
702 else if (b_describe_color_)
703 interpolateSingleChannel (indices, sqr_dists, index, binDistanceColor, nr_color_bins_, shot);
705 interpolateSingleChannel (indices, sqr_dists, index, binDistanceShape, nr_shape_bins_, shot);
708 this->normalizeHistogram (shot, descLength_);
712 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
714 const int index,
const pcl::Indices &indices,
const std::vector<float> &sqr_dists, Eigen::VectorXf &shot)
717 if (indices.size () < 5)
719 PCL_WARN (
"[pcl::%s::computePointSHOT] Warning! Neighborhood has less than 5 vertexes. Aborting description of point with index %d\n",
720 getClassName ().c_str (), (*indices_)[index]);
722 shot.setConstant(descLength_, 1, std::numeric_limits<float>::quiet_NaN () );
728 std::vector<double> binDistanceShape;
729 this->createBinDistanceShape (index, indices, binDistanceShape);
733 interpolateSingleChannel (indices, sqr_dists, index, binDistanceShape, nr_shape_bins_, shot);
736 this->normalizeHistogram (shot, descLength_);
742 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
745 descLength_ = nr_grid_sector_ * (nr_shape_bins_+1);
747 sqradius_ = search_radius_ * search_radius_;
748 radius3_4_ = (search_radius_*3) / 4;
749 radius1_4_ = search_radius_ / 4;
750 radius1_2_ = search_radius_ / 2;
752 assert(descLength_ == 352);
754 Eigen::VectorXf shot;
755 shot.setZero (descLength_);
760 std::vector<float> nn_dists (k_);
764 for (std::size_t idx = 0; idx < indices_->size (); ++idx)
766 bool lrf_is_nan =
false;
767 const PointRFT& current_frame = (*frames_)[idx];
768 if (!std::isfinite (current_frame.x_axis[0]) ||
769 !std::isfinite (current_frame.y_axis[0]) ||
770 !std::isfinite (current_frame.z_axis[0]))
772 PCL_WARN (
"[pcl::%s::computeFeature] The local reference frame is not valid! Aborting description of point with index %d\n",
773 getClassName ().c_str (), (*indices_)[idx]);
777 if (!
isFinite ((*input_)[(*indices_)[idx]]) ||
779 this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists) == 0)
782 for (
int d = 0; d < descLength_; ++d)
783 output[idx].descriptor[d] = std::numeric_limits<float>::quiet_NaN ();
784 for (
int d = 0; d < 9; ++d)
785 output[idx].rf[d] = std::numeric_limits<float>::quiet_NaN ();
792 computePointSHOT (
static_cast<int> (idx), nn_indices, nn_dists, shot);
795 for (
int d = 0; d < descLength_; ++d)
796 output[idx].descriptor[d] = shot[d];
797 for (
int d = 0; d < 3; ++d)
799 output[idx].rf[d + 0] = (*frames_)[idx].x_axis[d];
800 output[idx].rf[d + 3] = (*frames_)[idx].y_axis[d];
801 output[idx].rf[d + 6] = (*frames_)[idx].z_axis[d];
809 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT,
typename Po
intRFT>
void
813 descLength_ = (b_describe_shape_) ? nr_grid_sector_*(nr_shape_bins_+1) : 0;
814 descLength_ += (b_describe_color_) ? nr_grid_sector_*(nr_color_bins_+1) : 0;
816 assert( (!b_describe_color_ && b_describe_shape_ && descLength_ == 352) ||
817 (b_describe_color_ && !b_describe_shape_ && descLength_ == 992) ||
818 (b_describe_color_ && b_describe_shape_ && descLength_ == 1344)
822 sqradius_ = search_radius_*search_radius_;
823 radius3_4_ = (search_radius_*3) / 4;
824 radius1_4_ = search_radius_ / 4;
825 radius1_2_ = search_radius_ / 2;
827 Eigen::VectorXf shot;
828 shot.setZero (descLength_);
833 std::vector<float> nn_dists (k_);
837 for (std::size_t idx = 0; idx < indices_->size (); ++idx)
839 bool lrf_is_nan =
false;
840 const PointRFT& current_frame = (*frames_)[idx];
841 if (!std::isfinite (current_frame.x_axis[0]) ||
842 !std::isfinite (current_frame.y_axis[0]) ||
843 !std::isfinite (current_frame.z_axis[0]))
845 PCL_WARN (
"[pcl::%s::computeFeature] The local reference frame is not valid! Aborting description of point with index %d\n",
846 getClassName ().c_str (), (*indices_)[idx]);
850 if (!
isFinite ((*input_)[(*indices_)[idx]]) ||
852 this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists) == 0)
855 for (
int d = 0; d < descLength_; ++d)
856 output[idx].descriptor[d] = std::numeric_limits<float>::quiet_NaN ();
857 for (
int d = 0; d < 9; ++d)
858 output[idx].rf[d] = std::numeric_limits<float>::quiet_NaN ();
865 computePointSHOT (
static_cast<int> (idx), nn_indices, nn_dists, shot);
868 for (
int d = 0; d < descLength_; ++d)
869 output[idx].descriptor[d] = shot[d];
870 for (
int d = 0; d < 3; ++d)
872 output[idx].rf[d + 0] = (*frames_)[idx].x_axis[d];
873 output[idx].rf[d + 3] = (*frames_)[idx].y_axis[d];
874 output[idx].rf[d + 6] = (*frames_)[idx].z_axis[d];
879 #define PCL_INSTANTIATE_SHOTEstimationBase(T,NT,OutT,RFT) template class PCL_EXPORTS pcl::SHOTEstimationBase<T,NT,OutT,RFT>;
880 #define PCL_INSTANTIATE_SHOTEstimation(T,NT,OutT,RFT) template class PCL_EXPORTS pcl::SHOTEstimation<T,NT,OutT,RFT>;
881 #define PCL_INSTANTIATE_SHOTColorEstimation(T,NT,OutT,RFT) template class PCL_EXPORTS pcl::SHOTColorEstimation<T,NT,OutT,RFT>;
FeatureWithLocalReferenceFrames provides a public interface for descriptor extractor classes which ne...
bool is_dense
True if no points are invalid (e.g., have NaN or Inf values in any of their floating point fields).
SHOTColorEstimation estimates the Signature of Histograms of OrienTations (SHOT) descriptor for a giv...
void interpolateDoubleChannel(const pcl::Indices &indices, const std::vector< float > &sqr_dists, const int index, std::vector< double > &binDistanceShape, std::vector< double > &binDistanceColor, const int nr_bins_shape, const int nr_bins_color, Eigen::VectorXf &shot)
Quadrilinear interpolation; used when color and shape descriptions are both activated.
void computeFeature(pcl::PointCloud< PointOutT > &output) override
Estimate the Signatures of Histograms of OrienTations (SHOT) descriptors at a set of points given by ...
static void RGB2CIELAB(unsigned char R, unsigned char G, unsigned char B, float &L, float &A, float &B2)
Converts RGB triplets to CIELab space.
void computePointSHOT(const int index, const pcl::Indices &indices, const std::vector< float > &sqr_dists, Eigen::VectorXf &shot) override
Estimate the SHOT descriptor for a given point based on its spatial neighborhood of 3D points with no...
bool initCompute() override
This method should get called before starting the actual computation.
void normalizeHistogram(Eigen::VectorXf &shot, int desc_length)
Normalize the SHOT histogram.
void interpolateSingleChannel(const pcl::Indices &indices, const std::vector< float > &sqr_dists, const int index, std::vector< double > &binDistance, const int nr_bins, Eigen::VectorXf &shot)
Quadrilinear interpolation used when color and shape descriptions are NOT activated simultaneously.
void createBinDistanceShape(int index, const pcl::Indices &indices, std::vector< double > &bin_distance_shape)
Create a binned distance shape histogram.
void computeFeature(pcl::PointCloud< PointOutT > &output) override
Estimate the Signatures of Histograms of OrienTations (SHOT) descriptors at a set of points given by ...
void computePointSHOT(const int index, const pcl::Indices &indices, const std::vector< float > &sqr_dists, Eigen::VectorXf &shot) override
Estimate the SHOT descriptor for a given point based on its spatial neighborhood of 3D points with no...
SHOTLocalReferenceFrameEstimation estimates the Local Reference Frame used in the calculation of the ...
shared_ptr< SHOTLocalReferenceFrameEstimation< PointInT, PointOutT > > Ptr
float distance(const PointT &p1, const PointT &p2)
bool isFinite(const PointT &pt)
Tests if the 3D components of a point are all finite param[in] pt point to be tested return true if f...
IndicesAllocator<> Indices
Type used for indices in PCL.