40 #ifndef PCL_FEATURES_IMPL_RIFT_H_
41 #define PCL_FEATURES_IMPL_RIFT_H_
46 template <
typename Po
intInT,
typename GradientT,
typename Po
intOutT>
void
49 int p_idx,
float radius,
const std::vector<int> &indices,
50 const std::vector<float> &sqr_distances, Eigen::MatrixXf &rift_descriptor)
54 PCL_ERROR (
"[pcl::RIFTEstimation] Null indices points passed!\n");
59 int nr_distance_bins =
static_cast<int> (rift_descriptor.rows ());
60 int nr_gradient_bins =
static_cast<int> (rift_descriptor.cols ());
66 rift_descriptor.setZero ();
67 for (
size_t idx = 0; idx < indices.size (); ++idx)
71 Eigen::Map<const Eigen::Vector3f> gradient_vector (& (gradient.
points[indices[idx]].gradient[0]));
73 float gradient_magnitude = gradient_vector.norm ();
74 float gradient_angle_from_center = acosf (gradient_vector.dot ((point - p0).normalized ()) / gradient_magnitude);
76 gradient_angle_from_center = 0.0;
79 const float eps = std::numeric_limits<float>::epsilon ();
80 float d =
static_cast<float> (nr_distance_bins) * sqrtf (sqr_distances[idx]) / (radius + eps);
81 float g =
static_cast<float> (nr_gradient_bins) * gradient_angle_from_center / (static_cast<float> (M_PI) + eps);
84 int d_idx_min = (std::max)(static_cast<int> (ceil (d - 1)), 0);
85 int d_idx_max = (std::min)(static_cast<int> (floor (d + 1)), nr_distance_bins - 1);
86 int g_idx_min =
static_cast<int> (ceil (g - 1));
87 int g_idx_max =
static_cast<int> (floor (g + 1));
90 for (
int g_idx = g_idx_min; g_idx <= g_idx_max; ++g_idx)
93 int g_idx_wrapped = ((g_idx + nr_gradient_bins) % nr_gradient_bins);
95 for (
int d_idx = d_idx_min; d_idx <= d_idx_max; ++d_idx)
98 float w = (1.0f - fabsf (d - static_cast<float> (d_idx))) * (1.0f - fabsf (g - static_cast<float> (g_idx)));
100 rift_descriptor (d_idx, g_idx_wrapped) += w * gradient_magnitude;
106 rift_descriptor.normalize ();
111 template <
typename Po
intInT,
typename GradientT,
typename Po
intOutT>
void
115 if (search_radius_ == 0.0)
117 PCL_ERROR (
"[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n",
118 getClassName ().c_str ());
119 output.width = output.height = 0;
120 output.points.clear ();
125 if (nr_gradient_bins_ <= 0)
127 PCL_ERROR (
"[pcl::%s::computeFeature] The number of gradient bins must be greater than zero!\n",
128 getClassName ().c_str ());
129 output.width = output.height = 0;
130 output.points.clear ();
133 if (nr_distance_bins_ <= 0)
135 PCL_ERROR (
"[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n",
136 getClassName ().c_str ());
137 output.width = output.height = 0;
138 output.points.clear ();
145 PCL_ERROR (
"[pcl::%s::computeFeature] No input gradient was given!\n", getClassName ().c_str ());
146 output.width = output.height = 0;
147 output.points.clear ();
150 if (gradient_->points.size () != surface_->points.size ())
152 PCL_ERROR (
"[pcl::%s::computeFeature] ", getClassName ().c_str ());
153 PCL_ERROR (
"The number of points in the input dataset differs from the number of points in the gradient!\n");
154 output.width = output.height = 0;
155 output.points.clear ();
159 Eigen::MatrixXf rift_descriptor (nr_distance_bins_, nr_gradient_bins_);
160 std::vector<int> nn_indices;
161 std::vector<float> nn_dist_sqr;
164 for (
size_t idx = 0; idx < indices_->size (); ++idx)
167 tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr);
170 computeRIFT (*surface_, *gradient_, (*indices_)[idx], static_cast<float> (search_radius_), nn_indices, nn_dist_sqr, rift_descriptor);
174 for (
int g_bin = 0; g_bin < rift_descriptor.cols (); ++g_bin)
175 for (
int d_bin = 0; d_bin < rift_descriptor.rows (); ++d_bin)
176 output.points[idx].histogram[bin++] = rift_descriptor (d_bin, g_bin);
181 template <
typename Po
intInT,
typename GradientT>
void
187 if (search_radius_ == 0.0)
189 PCL_ERROR (
"[pcl::%s::computeFeature] The search radius must be set before computing the feature!\n",
190 getClassName ().c_str ());
192 output.
points.resize (0, 0);
197 if (nr_gradient_bins_ <= 0)
199 PCL_ERROR (
"[pcl::%s::computeFeature] The number of gradient bins must be greater than zero!\n",
200 getClassName ().c_str ());
202 output.
points.resize (0, 0);
205 if (nr_distance_bins_ <= 0)
207 PCL_ERROR (
"[pcl::%s::computeFeature] The number of distance bins must be greater than zero!\n",
208 getClassName ().c_str ());
210 output.
points.resize (0, 0);
217 PCL_ERROR (
"[pcl::%s::computeFeature] No input gradient was given!\n", getClassName ().c_str ());
219 output.
points.resize (0, 0);
222 if (gradient_->points.size () != surface_->points.size ())
224 PCL_ERROR (
"[pcl::%s::computeFeature] ", getClassName ().c_str ());
225 PCL_ERROR (
"The number of points in the input dataset differs from the number of points in the gradient!\n");
227 output.
points.resize (0, 0);
232 output.
points.resize (indices_->size (), nr_gradient_bins_ * nr_distance_bins_);
233 Eigen::MatrixXf rift_descriptor (nr_distance_bins_, nr_gradient_bins_);
234 std::vector<int> nn_indices;
235 std::vector<float> nn_dist_sqr;
239 for (
size_t idx = 0; idx < indices_->size (); ++idx)
242 if (tree_->radiusSearch ((*indices_)[idx], search_radius_, nn_indices, nn_dist_sqr) == 0)
244 output.
points.row (idx).setConstant (std::numeric_limits<float>::quiet_NaN ());
250 this->
computeRIFT (*surface_, *gradient_, (*indices_)[idx], static_cast<float> (search_radius_), nn_indices, nn_dist_sqr,
255 for (
int g_bin = 0; g_bin < rift_descriptor.cols (); ++g_bin)
256 for (
int d_bin = 0; d_bin < rift_descriptor.rows (); ++d_bin)
257 output.
points (idx, bin++) = rift_descriptor (d_bin, g_bin);
262 #define PCL_INSTANTIATE_RIFTEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::RIFTEstimation<T,NT,OutT>;
264 #endif // PCL_FEATURES_IMPL_RIFT_H_