38 #ifndef PCL_FEATURES_IMPL_RSD_H_
39 #define PCL_FEATURES_IMPL_RSD_H_
45 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT> Eigen::MatrixXf
47 const std::vector<int> &indices,
double max_dist,
48 int nr_subdiv,
double plane_radius, PointOutT &radii,
bool compute_histogram)
51 Eigen::MatrixXf histogram;
52 if (compute_histogram)
53 histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);
56 if (indices.size () < 2)
64 std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
65 min_max_angle_by_dist[0].resize (2);
66 min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
67 for (
int di=1; di<nr_subdiv; di++)
69 min_max_angle_by_dist[di].resize (2);
70 min_max_angle_by_dist[di][0] = +DBL_MAX;
71 min_max_angle_by_dist[di][1] = -DBL_MAX;
75 std::vector<int>::const_iterator i, begin (indices.begin()), end (indices.end());
76 for(i = begin+1; i != end; ++i)
79 double cosine = normals->points[*i].normal[0] * normals->points[*begin].normal[0] +
80 normals->points[*i].normal[1] * normals->points[*begin].normal[1] +
81 normals->points[*i].normal[2] * normals->points[*begin].normal[2];
82 if (cosine > 1) cosine = 1;
83 if (cosine < -1) cosine = -1;
84 double angle = acos (cosine);
85 if (angle > M_PI/2) angle = M_PI - angle;
88 double dist =
sqrt ((surface->points[*i].x - surface->points[*begin].x) * (surface->points[*i].x - surface->points[*begin].x) +
89 (surface->points[*i].y - surface->points[*begin].y) * (surface->points[*i].y - surface->points[*begin].y) +
90 (surface->points[*i].z - surface->points[*begin].z) * (surface->points[*i].z - surface->points[*begin].z));
96 int bin_d = (int) floor (nr_subdiv * dist / max_dist);
97 if (compute_histogram)
99 int bin_a = std::min (nr_subdiv-1, (
int) floor (nr_subdiv * angle / (M_PI/2)));
100 histogram(bin_a, bin_d)++;
104 if (min_max_angle_by_dist[bin_d][0] > angle) min_max_angle_by_dist[bin_d][0] = angle;
105 if (min_max_angle_by_dist[bin_d][1] < angle) min_max_angle_by_dist[bin_d][1] = angle;
109 double Amint_Amin = 0, Amint_d = 0;
110 double Amaxt_Amax = 0, Amaxt_d = 0;
111 for (
int di=0; di<nr_subdiv; di++)
114 if (min_max_angle_by_dist[di][1] >= 0)
116 double p_min = min_max_angle_by_dist[di][0];
117 double p_max = min_max_angle_by_dist[di][1];
118 double f = (di+0.5)*max_dist/nr_subdiv;
119 Amint_Amin += p_min * p_min;
120 Amint_d += p_min * f;
121 Amaxt_Amax += p_max * p_max;
122 Amaxt_d += p_max * f;
125 float min_radius = Amint_Amin == 0 ? plane_radius : std::min (Amint_d/Amint_Amin, plane_radius);
126 float max_radius = Amaxt_Amax == 0 ? plane_radius : std::min (Amaxt_d/Amaxt_Amax, plane_radius);
131 if (min_radius < max_radius)
133 radii.r_min = min_radius;
134 radii.r_max = max_radius;
138 radii.r_max = min_radius;
139 radii.r_min = max_radius;
146 template <
typename Po
intNT,
typename Po
intOutT> Eigen::MatrixXf
148 const std::vector<int> &indices,
const std::vector<float> &sqr_dists,
double max_dist,
149 int nr_subdiv,
double plane_radius, PointOutT &radii,
bool compute_histogram)
152 Eigen::MatrixXf histogram;
153 if (compute_histogram)
154 histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);
157 if (indices.size () < 2)
165 std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
166 min_max_angle_by_dist[0].resize (2);
167 min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
168 for (
int di=1; di<nr_subdiv; di++)
170 min_max_angle_by_dist[di].resize (2);
171 min_max_angle_by_dist[di][0] = +DBL_MAX;
172 min_max_angle_by_dist[di][1] = -DBL_MAX;
176 std::vector<int>::const_iterator i, begin (indices.begin()), end (indices.end());
177 for(i = begin+1; i != end; ++i)
180 double cosine = normals->points[*i].normal[0] * normals->points[*begin].normal[0] +
181 normals->points[*i].normal[1] * normals->points[*begin].normal[1] +
182 normals->points[*i].normal[2] * normals->points[*begin].normal[2];
183 if (cosine > 1) cosine = 1;
184 if (cosine < -1) cosine = -1;
185 double angle = acos (cosine);
186 if (angle > M_PI/2) angle = M_PI - angle;
189 double dist =
sqrt (sqr_dists[i-begin]);
195 int bin_d = (int) floor (nr_subdiv * dist / max_dist);
196 if (compute_histogram)
198 int bin_a = std::min (nr_subdiv-1, (
int) floor (nr_subdiv * angle / (M_PI/2)));
199 histogram(bin_a, bin_d)++;
203 if (min_max_angle_by_dist[bin_d][0] > angle) min_max_angle_by_dist[bin_d][0] = angle;
204 if (min_max_angle_by_dist[bin_d][1] < angle) min_max_angle_by_dist[bin_d][1] = angle;
208 double Amint_Amin = 0, Amint_d = 0;
209 double Amaxt_Amax = 0, Amaxt_d = 0;
210 for (
int di=0; di<nr_subdiv; di++)
213 if (min_max_angle_by_dist[di][1] >= 0)
215 double p_min = min_max_angle_by_dist[di][0];
216 double p_max = min_max_angle_by_dist[di][1];
217 double f = (di+0.5)*max_dist/nr_subdiv;
218 Amint_Amin += p_min * p_min;
219 Amint_d += p_min * f;
220 Amaxt_Amax += p_max * p_max;
221 Amaxt_d += p_max * f;
224 float min_radius = Amint_Amin == 0 ? plane_radius : std::min (Amint_d/Amint_Amin, plane_radius);
225 float max_radius = Amaxt_Amax == 0 ? plane_radius : std::min (Amaxt_d/Amaxt_Amax, plane_radius);
230 if (min_radius < max_radius)
232 radii.r_min = min_radius;
233 radii.r_max = max_radius;
237 radii.r_max = min_radius;
238 radii.r_min = max_radius;
245 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
249 if (search_radius_ < 0)
251 PCL_ERROR (
"[pcl::%s::computeFeature] A search radius needs to be set!\n", getClassName ().c_str ());
252 output.width = output.height = 0;
253 output.points.clear ();
259 std::vector<int> nn_indices;
260 std::vector<float> nn_sqr_dists;
263 if (save_histograms_)
266 histograms_.reset (
new std::vector<Eigen::MatrixXf, Eigen::aligned_allocator<Eigen::MatrixXf> >);
267 histograms_->reserve (output.points.size ());
270 for (
size_t idx = 0; idx < indices_->size (); ++idx)
273 this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
275 histograms_->push_back (
computeRSD (normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output.points[idx],
true));
281 for (
size_t idx = 0; idx < indices_->size (); ++idx)
284 this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
286 computeRSD (normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output.points[idx],
false);
291 #define PCL_INSTANTIATE_RSDEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::RSDEstimation<T,NT,OutT>;
293 #endif // PCL_FEATURES_IMPL_VFH_H_