41 #ifndef PCL_FEATURES_IMPL_RSD_H_
42 #define PCL_FEATURES_IMPL_RSD_H_
45 #include <pcl/features/rsd.h>
48 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT> Eigen::MatrixXf
51 int nr_subdiv,
double plane_radius, PointOutT &radii,
bool compute_histogram)
54 Eigen::MatrixXf histogram;
55 if (compute_histogram)
56 histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);
59 if (indices.size () < 2)
67 std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
68 for (
auto& minmax: min_max_angle_by_dist)
71 minmax[0] = std::numeric_limits<double>::max();
72 minmax[1] = -std::numeric_limits<double>::max();
74 min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
77 pcl::Indices::const_iterator i, begin (indices.begin()), end (indices.end());
78 for (i = begin+1; i != end; ++i)
81 double cosine = normals[*i].normal[0] * normals[*begin].normal[0] +
82 normals[*i].normal[1] * normals[*begin].normal[1] +
83 normals[*i].normal[2] * normals[*begin].normal[2];
84 if (cosine > 1) cosine = 1;
85 if (cosine < -1) cosine = -1;
86 double angle = std::acos (cosine);
87 if (angle >
M_PI/2) angle =
M_PI - angle;
90 double dist = sqrt ((surface[*i].x - surface[*begin].x) * (surface[*i].x - surface[*begin].x) +
91 (surface[*i].y - surface[*begin].y) * (surface[*i].y - surface[*begin].y) +
92 (surface[*i].z - surface[*begin].z) * (surface[*i].z - surface[*begin].z));
98 int bin_d =
static_cast<int> (std::floor (nr_subdiv * dist / max_dist));
99 if (compute_histogram)
101 int bin_a = std::min (nr_subdiv-1,
static_cast<int> (std::floor (nr_subdiv * angle / (
M_PI/2))));
102 histogram(bin_a, bin_d)++;
106 min_max_angle_by_dist[bin_d][0] = std::min(angle, min_max_angle_by_dist[bin_d][0]);
107 min_max_angle_by_dist[bin_d][1] = std::max(angle, min_max_angle_by_dist[bin_d][1]);
111 double Amint_Amin = 0, Amint_d = 0;
112 double Amaxt_Amax = 0, Amaxt_d = 0;
113 for (
int di=0; di<nr_subdiv; di++)
116 if (min_max_angle_by_dist[di][1] >= 0)
118 double p_min = min_max_angle_by_dist[di][0];
119 double p_max = min_max_angle_by_dist[di][1];
120 double f = (di+0.5)*max_dist/nr_subdiv;
121 Amint_Amin += p_min * p_min;
122 Amint_d += p_min * f;
123 Amaxt_Amax += p_max * p_max;
124 Amaxt_d += p_max * f;
127 float min_radius = Amint_Amin == 0.0f ?
static_cast<float>(plane_radius) :
static_cast<float>(std::min (Amint_d/Amint_Amin, plane_radius));
128 float max_radius = Amaxt_Amax == 0.0f ?
static_cast<float>(plane_radius) :
static_cast<float>(std::min (Amaxt_d/Amaxt_Amax, plane_radius));
133 if (min_radius < max_radius)
135 radii.r_min = min_radius;
136 radii.r_max = max_radius;
140 radii.r_max = min_radius;
141 radii.r_min = max_radius;
148 template <
typename Po
intNT,
typename Po
intOutT> Eigen::MatrixXf
150 const pcl::Indices &indices,
const std::vector<float> &sqr_dists,
double max_dist,
151 int nr_subdiv,
double plane_radius, PointOutT &radii,
bool compute_histogram)
154 Eigen::MatrixXf histogram;
155 if (compute_histogram)
156 histogram = Eigen::MatrixXf::Zero (nr_subdiv, nr_subdiv);
159 if (indices.size () < 2)
167 std::vector<std::vector<double> > min_max_angle_by_dist (nr_subdiv);
168 min_max_angle_by_dist[0].resize (2);
169 min_max_angle_by_dist[0][0] = min_max_angle_by_dist[0][1] = 0.0;
170 for (
int di=1; di<nr_subdiv; di++)
172 min_max_angle_by_dist[di].resize (2);
173 min_max_angle_by_dist[di][0] = std::numeric_limits<double>::max();
174 min_max_angle_by_dist[di][1] = std::numeric_limits<double>::lowest();
178 pcl::Indices::const_iterator i, begin (indices.begin()), end (indices.end());
179 for (i = begin+1; i != end; ++i)
182 double cosine = normals[*i].normal[0] * normals[*begin].normal[0] +
183 normals[*i].normal[1] * normals[*begin].normal[1] +
184 normals[*i].normal[2] * normals[*begin].normal[2];
185 if (cosine > 1) cosine = 1;
186 if (cosine < -1) cosine = -1;
187 double angle = std::acos (cosine);
188 if (angle >
M_PI/2) angle =
M_PI - angle;
191 double dist = sqrt (sqr_dists[i-begin]);
197 int bin_d =
static_cast<int> (std::floor (nr_subdiv * dist / max_dist));
198 if (compute_histogram)
200 int bin_a = std::min (nr_subdiv-1,
static_cast<int> (std::floor (nr_subdiv * angle / (
M_PI/2))));
201 histogram(bin_a, bin_d)++;
205 if (min_max_angle_by_dist[bin_d][0] > angle) min_max_angle_by_dist[bin_d][0] = angle;
206 if (min_max_angle_by_dist[bin_d][1] < angle) min_max_angle_by_dist[bin_d][1] = angle;
210 double Amint_Amin = 0, Amint_d = 0;
211 double Amaxt_Amax = 0, Amaxt_d = 0;
212 for (
int di=0; di<nr_subdiv; di++)
215 if (min_max_angle_by_dist[di][1] >= 0)
217 double p_min = min_max_angle_by_dist[di][0];
218 double p_max = min_max_angle_by_dist[di][1];
219 double f = (di+0.5)*max_dist/nr_subdiv;
220 Amint_Amin += p_min * p_min;
221 Amint_d += p_min * f;
222 Amaxt_Amax += p_max * p_max;
223 Amaxt_d += p_max * f;
226 float min_radius = Amint_Amin == 0.0f ?
static_cast<float>(plane_radius) :
static_cast<float>(std::min (Amint_d/Amint_Amin, plane_radius));
227 float max_radius = Amaxt_Amax == 0.0f ?
static_cast<float>(plane_radius) :
static_cast<float>(std::min (Amaxt_d/Amaxt_Amax, plane_radius));
232 if (min_radius < max_radius)
234 radii.r_min = min_radius;
235 radii.r_max = max_radius;
239 radii.r_max = min_radius;
240 radii.r_min = max_radius;
247 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
251 if (search_radius_ < 0)
253 PCL_ERROR (
"[pcl::%s::computeFeature] A search radius needs to be set!\n", getClassName ().c_str ());
262 std::vector<float> nn_sqr_dists;
265 if (save_histograms_)
268 histograms_.reset (
new std::vector<Eigen::MatrixXf, Eigen::aligned_allocator<Eigen::MatrixXf> >);
269 histograms_->reserve (output.
size ());
272 for (std::size_t idx = 0; idx < indices_->size (); ++idx)
275 this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
277 histograms_->push_back (
computeRSD (*normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output[idx],
true));
283 for (std::size_t idx = 0; idx < indices_->size (); ++idx)
286 this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_sqr_dists);
288 computeRSD (*normals_, nn_indices, nn_sqr_dists, search_radius_, nr_subdiv_, plane_radius_, output[idx],
false);
293 #define PCL_INSTANTIATE_RSDEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::RSDEstimation<T,NT,OutT>;
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).
void clear()
Removes all points in a cloud and sets the width and height to 0.
void computeFeature(PointCloudOut &output) override
Estimate the estimates the Radius-based Surface Descriptor (RSD) at a set of points given by <setInpu...
Eigen::MatrixXf computeRSD(const pcl::PointCloud< PointInT > &surface, const pcl::PointCloud< PointNT > &normals, const pcl::Indices &indices, double max_dist, int nr_subdiv, double plane_radius, PointOutT &radii, bool compute_histogram=false)
Estimate the Radius-based Surface Descriptor (RSD) for a given point based on its spatial neighborhoo...
IndicesAllocator<> Indices
Type used for indices in PCL.