40 #ifndef PCL_FEATURES_IMPL_USC_HPP_
41 #define PCL_FEATURES_IMPL_USC_HPP_
50 template <
typename Po
intInT,
typename Po
intOutT,
typename Po
intRFT>
bool
53 if (!Feature<PointInT, PointOutT>::initCompute ())
55 PCL_ERROR (
"[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
60 typename SHOTLocalReferenceFrameEstimation<PointInT, PointRFT>::Ptr lrf_estimator(
new SHOTLocalReferenceFrameEstimation<PointInT, PointRFT>());
61 lrf_estimator->setRadiusSearch (local_radius_);
62 lrf_estimator->setInputCloud (input_);
63 lrf_estimator->setIndices (indices_);
65 lrf_estimator->setSearchSurface(surface_);
67 if (!FeatureWithLocalReferenceFrames<PointInT, PointRFT>::initLocalReferenceFrames (indices_->size (), lrf_estimator))
69 PCL_ERROR (
"[pcl::%s::initCompute] Init failed.\n", getClassName ().c_str ());
73 if (search_radius_< min_radius_)
75 PCL_ERROR (
"[pcl::%s::initCompute] search_radius_ must be GREATER than min_radius_.\n", getClassName ().c_str ());
80 descriptor_length_ = elevation_bins_ * azimuth_bins_ * radius_bins_;
83 float azimuth_interval = 360.0f /
static_cast<float> (azimuth_bins_);
84 float elevation_interval = 180.0f /
static_cast<float> (elevation_bins_);
87 radii_interval_.clear ();
88 phi_divisions_.clear ();
89 theta_divisions_.clear ();
93 radii_interval_.resize (radius_bins_ + 1);
94 for (
size_t j = 0; j < radius_bins_ + 1; j++)
95 radii_interval_[j] = static_cast<float> (exp (log (min_radius_) + ((static_cast<float> (j) / static_cast<float> (radius_bins_)) * log (search_radius_/min_radius_))));
98 theta_divisions_.resize (elevation_bins_+1);
99 for (
size_t k = 0; k < elevation_bins_+1; k++)
100 theta_divisions_[k] = static_cast<float> (k) * elevation_interval;
103 phi_divisions_.resize (azimuth_bins_+1);
104 for (
size_t l = 0; l < azimuth_bins_+1; l++)
105 phi_divisions_[l] = static_cast<float> (l) * azimuth_interval;
112 float e = 1.0f / 3.0f;
114 volume_lut_.resize (radius_bins_ * elevation_bins_ * azimuth_bins_);
116 for (
size_t j = 0; j < radius_bins_; j++)
119 float integr_r = (radii_interval_[j+1]*radii_interval_[j+1]*radii_interval_[j+1] / 3) - (radii_interval_[j]*radii_interval_[j]*radii_interval_[j]/ 3);
121 for (
size_t k = 0; k < elevation_bins_; k++)
124 float integr_theta = cosf (
deg2rad (theta_divisions_[k])) - cosf (
deg2rad (theta_divisions_[k+1]));
126 float V = integr_phi * integr_theta * integr_r;
132 for (
size_t l = 0; l < azimuth_bins_; l++)
135 volume_lut_[(l*elevation_bins_*radius_bins_) + k*radius_bins_ + j] = 1.0f / powf (V, e);
142 template <
typename Po
intInT,
typename Po
intOutT,
typename Po
intRFT>
void
147 const Eigen::Vector3f& x_axis = frames_->points[index].x_axis.getNormalVector3fMap ();
149 const Eigen::Vector3f& normal = frames_->points[index].z_axis.getNormalVector3fMap ();
152 std::vector<int> nn_indices;
153 std::vector<float> nn_dists;
154 const size_t neighb_cnt = searchForNeighbors ((*indices_)[index], search_radius_, nn_indices, nn_dists);
156 for (
size_t ne = 0; ne < neighb_cnt; ne++)
161 Eigen::Vector3f neighbour = surface_->points[nn_indices[ne]].getVector3fMap ();
166 float r =
sqrt (nn_dists[ne]);
169 Eigen::Vector3f proj;
177 Eigen::Vector3f cross = x_axis.cross (proj);
178 float phi =
rad2deg (std::atan2 (cross.norm (), x_axis.dot (proj)));
179 phi = cross.dot (normal) < 0.f ? (360.0f - phi) : phi;
181 Eigen::Vector3f no = neighbour - origin;
183 float theta = normal.dot (no);
184 theta =
pcl::rad2deg (acosf (std::min (1.0f, std::max (-1.0f, theta))));
192 for (
size_t rad = 1; rad < radius_bins_ + 1; rad++)
194 if (r <= radii_interval_[rad])
201 for (
size_t ang = 1; ang < elevation_bins_ + 1; ang++)
203 if (theta <= theta_divisions_[ang])
210 for (
size_t ang = 1; ang < azimuth_bins_ + 1; ang++)
212 if (phi <= phi_divisions_[ang])
220 std::vector<int> neighbour_indices;
221 std::vector<float> neighbour_didtances;
222 float point_density =
static_cast<float> (searchForNeighbors (*surface_, nn_indices[ne], point_density_radius_, neighbour_indices, neighbour_didtances));
224 float w = (1.0f / point_density) * volume_lut_[(l*elevation_bins_*radius_bins_) +
229 if (w == std::numeric_limits<float>::infinity ())
230 PCL_ERROR (
"Shape Context Error INF!\n");
232 PCL_ERROR (
"Shape Context Error IND!\n");
234 desc[(l*elevation_bins_*radius_bins_) + (k*radius_bins_) + j] += w;
236 assert (desc[(l*elevation_bins_*radius_bins_) + (k*radius_bins_) + j] >= 0);
241 template <
typename Po
intInT,
typename Po
intOutT,
typename Po
intRFT>
void
244 for (
size_t point_index = 0; point_index < indices_->size (); point_index++)
246 output[point_index].descriptor.resize (descriptor_length_);
247 for (
int d = 0; d < 9; ++d)
248 output.points[point_index].rf[d] = frames_->points[point_index].rf[ (4*(d/3) + (d%3)) ];
250 computePointDescriptor (point_index, output[point_index].descriptor);
255 template <
typename Po
intInT,
typename Po
intRFT>
void
258 output.
points.resize (indices_->size (), descriptor_length_ + 9);
260 for (
size_t point_index = 0; point_index < indices_->size (); point_index++)
262 for (
int d = 0; d < 9; ++d)
263 output.
points (point_index, d) = frames_->points[point_index].rf[ (4*(d/3) + (d%3)) ];
265 std::vector<float> descriptor (descriptor_length_);
266 computePointDescriptor (point_index, descriptor);
267 for (
size_t j = 0; j < descriptor_length_; ++j)
268 output.
points (point_index, 9 + j) = descriptor[j];
272 #define PCL_INSTANTIATE_UniqueShapeContext(T,OutT,RFT) template class PCL_EXPORTS pcl::UniqueShapeContext<T,OutT,RFT>;