40 #ifndef PCL_FEATURES_IMPL_3DSC_HPP_
41 #define PCL_FEATURES_IMPL_3DSC_HPP_
50 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
bool
53 if (!FeatureFromNormals<PointInT, PointNT, PointOutT>::initCompute ())
55 PCL_ERROR (
"[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
59 if (search_radius_< min_radius_)
61 PCL_ERROR (
"[pcl::%s::initCompute] search_radius_ must be GREATER than min_radius_.\n", getClassName ().c_str ());
66 descriptor_length_ = elevation_bins_ * azimuth_bins_ * radius_bins_;
69 float azimuth_interval = 360.0f /
static_cast<float> (azimuth_bins_);
70 float elevation_interval = 180.0f /
static_cast<float> (elevation_bins_);
73 radii_interval_.clear ();
74 phi_divisions_.clear ();
75 theta_divisions_.clear ();
79 radii_interval_.resize (radius_bins_ + 1);
80 for (
size_t j = 0; j < radius_bins_ + 1; j++)
81 radii_interval_[j] = static_cast<float> (exp (log (min_radius_) + ((static_cast<float> (j) / static_cast<float> (radius_bins_)) * log (search_radius_ / min_radius_))));
84 theta_divisions_.resize (elevation_bins_ + 1);
85 for (
size_t k = 0; k < elevation_bins_ + 1; k++)
86 theta_divisions_[k] = static_cast<float> (k) * elevation_interval;
89 phi_divisions_.resize (azimuth_bins_ + 1);
90 for (
size_t l = 0; l < azimuth_bins_ + 1; l++)
91 phi_divisions_[l] = static_cast<float> (l) * azimuth_interval;
98 float e = 1.0f / 3.0f;
100 volume_lut_.resize (radius_bins_ * elevation_bins_ * azimuth_bins_);
102 for (
size_t j = 0; j < radius_bins_; j++)
105 float integr_r = (radii_interval_[j+1] * radii_interval_[j+1] * radii_interval_[j+1] / 3.0f) - (radii_interval_[j] * radii_interval_[j] * radii_interval_[j] / 3.0f);
107 for (
size_t k = 0; k < elevation_bins_; k++)
112 float V = integr_phi * integr_theta * integr_r;
118 for (
size_t l = 0; l < azimuth_bins_; l++)
122 volume_lut_[(l*elevation_bins_*radius_bins_) + k*radius_bins_ + j] = 1.0f / powf (V, e);
130 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
bool
135 Eigen::Map<Eigen::Vector3f> x_axis (rf);
136 Eigen::Map<Eigen::Vector3f> y_axis (rf + 3);
137 Eigen::Map<Eigen::Vector3f> normal (rf + 6);
140 std::vector<int> nn_indices;
141 std::vector<float> nn_dists;
142 const size_t neighb_cnt = searchForNeighbors ((*indices_)[index], search_radius_, nn_indices, nn_dists);
145 for (
size_t i = 0; i < desc.size (); ++i)
146 desc[i] = std::numeric_limits<float>::quiet_NaN ();
148 memset (rf, 0,
sizeof (rf[0]) * 9);
152 float minDist = std::numeric_limits<float>::max ();
154 for (
size_t i = 0; i < nn_indices.size (); i++)
156 if (nn_dists[i] < minDist)
158 minDist = nn_dists[i];
159 minIndex = nn_indices[i];
164 Vector3fMapConst origin = input_->points[(*indices_)[index]].getVector3fMap ();
167 normal = normals[minIndex].getNormalVector3fMap ();
170 x_axis[0] =
static_cast<float> (rnd ());
171 x_axis[1] =
static_cast<float> (rnd ());
172 x_axis[2] =
static_cast<float> (rnd ());
174 x_axis[2] = - (normal[0]*x_axis[0] + normal[1]*x_axis[1]) / normal[2];
176 x_axis[1] = - (normal[0]*x_axis[0] + normal[2]*x_axis[2]) / normal[1];
178 x_axis[0] = - (normal[1]*x_axis[1] + normal[2]*x_axis[2]) / normal[0];
183 assert (
pcl::utils::equal (x_axis[0]*normal[0] + x_axis[1]*normal[1] + x_axis[2]*normal[2], 0.0f, 1E-6f));
186 y_axis = normal.cross (x_axis);
189 for (
size_t ne = 0; ne < neighb_cnt; ne++)
194 Eigen::Vector3f neighbour = surface_->points[nn_indices[ne]].getVector3fMap ();
198 float r =
sqrt (nn_dists[ne]);
201 Eigen::Vector3f proj;
209 Eigen::Vector3f cross = x_axis.cross (proj);
210 float phi =
pcl::rad2deg (std::atan2 (cross.norm (), x_axis.dot (proj)));
211 phi = cross.dot (normal) < 0.f ? (360.0f - phi) : phi;
213 Eigen::Vector3f no = neighbour - origin;
215 float theta = normal.dot (no);
216 theta =
pcl::rad2deg (acosf (std::min (1.0f, std::max (-1.0f, theta))));
224 for (
size_t rad = 1; rad < radius_bins_+1; rad++)
226 if (r <= radii_interval_[rad])
233 for (
size_t ang = 1; ang < elevation_bins_+1; ang++)
235 if (theta <= theta_divisions_[ang])
242 for (
size_t ang = 1; ang < azimuth_bins_+1; ang++)
244 if (phi <= phi_divisions_[ang])
252 std::vector<int> neighbour_indices;
253 std::vector<float> neighbour_distances;
254 int point_density = searchForNeighbors (*surface_, nn_indices[ne], point_density_radius_, neighbour_indices, neighbour_distances);
256 if (point_density == 0)
259 float w = (1.0f /
static_cast<float> (point_density)) *
260 volume_lut_[(l*elevation_bins_*radius_bins_) + (k*radius_bins_) + j];
263 if (w == std::numeric_limits<float>::infinity ())
264 PCL_ERROR (
"Shape Context Error INF!\n");
266 PCL_ERROR (
"Shape Context Error IND!\n");
268 desc[(l*elevation_bins_*radius_bins_) + (k*radius_bins_) + j] += w;
270 assert (desc[(l*elevation_bins_*radius_bins_) + (k*radius_bins_) + j] >= 0);
274 memset (rf, 0,
sizeof (rf[0]) * 9);
279 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
281 size_t block_size, std::vector<float>& desc)
283 assert (desc.size () == descriptor_length_);
285 desc.resize (descriptor_length_ * azimuth_bins_);
288 for (
size_t l = 1; l < azimuth_bins_; l++)
289 for (
size_t bin = 0; bin < descriptor_length_; bin++)
290 desc[(l * descriptor_length_) + bin] = desc[(l*block_size + bin) % descriptor_length_];
294 template <
typename Po
intInT,
typename Po
intNT,
typename Po
intOutT>
void
297 output.is_dense =
true;
299 for (
size_t point_index = 0; point_index < indices_->size (); point_index++)
301 output[point_index].descriptor.resize (descriptor_length_);
304 if (!
isFinite ((*input_)[(*indices_)[point_index]]))
306 for (
size_t i = 0; i < descriptor_length_; ++i)
307 output[point_index].descriptor[i] = std::numeric_limits<float>::quiet_NaN ();
309 memset (output[point_index].rf, 0,
sizeof (output[point_index].rf[0]) * 9);
310 output.is_dense =
false;
314 if (!computePoint (point_index, *normals_, output[point_index].rf, output[point_index].descriptor))
315 output.is_dense =
false;
320 template <
typename Po
intInT,
typename Po
intNT>
void
326 output.
channels[
"3dsc"].name =
"3dsc";
329 output.
channels[
"3dsc"].count =
static_cast<uint32_t
> (descriptor_length_) + 9;
333 output.
points.resize (indices_->size (), descriptor_length_ + 9);
339 for (
size_t point_index = 0; point_index < indices_->size (); point_index++)
342 if (!
isFinite ((*input_)[(*indices_)[point_index]]))
344 output.
points.row (point_index).setConstant (std::numeric_limits<float>::quiet_NaN ());
349 std::vector<float> descriptor (descriptor_length_);
350 if (!this->computePoint (point_index, *normals_, rf, descriptor))
352 for (
int j = 0; j < 9; ++j)
353 output.
points (point_index, j) = rf[j];
354 for (
size_t j = 0; j < descriptor_length_; ++j)
355 output.
points (point_index, 9 + j) = descriptor[j];
359 #define PCL_INSTANTIATE_ShapeContext3DEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::ShapeContext3DEstimation<T,NT,OutT>;