40 #ifndef PCL_SURFACE_IMPL_MLS_H_
41 #define PCL_SURFACE_IMPL_MLS_H_
51 template <
typename Po
intInT,
typename Po
intOutT>
void
59 normals_->header = input_->header;
61 normals_->width = normals_->height = 0;
62 normals_->points.clear ();
67 output.
header = input_->header;
71 if (search_radius_ <= 0 || sqr_gauss_param_ <= 0)
73 PCL_ERROR (
"[pcl::%s::reconstruct] Invalid search radius (%f) or Gaussian parameter (%f)!\n", getClassName ().c_str (), search_radius_, sqr_gauss_param_);
85 if (input_->isOrganized ())
89 setSearchMethod (tree);
93 tree_->setInputCloud (input_, indices_);
96 switch (upsample_method_)
98 case (RANDOM_UNIFORM_DENSITY):
100 boost::mt19937 *rng =
new boost::mt19937 (static_cast<unsigned int>(std::time(0)));
101 float tmp =
static_cast<float> (search_radius_ / 2.0f);
102 boost::uniform_real<float> *uniform_distrib =
new boost::uniform_real<float> (-tmp, tmp);
103 rng_uniform_distribution_ =
new boost::variate_generator<boost::mt19937, boost::uniform_real<float> > (*rng, *uniform_distrib);
106 case (VOXEL_GRID_DILATION):
108 mls_results_.resize (input_->size ());
116 performProcessing (output);
118 if (compute_normals_)
120 normals_->height = 1;
121 normals_->width =
static_cast<uint32_t
> (normals_->size ());
124 for (
unsigned int i = 0; i < output.
size (); ++i)
137 output.
width =
static_cast<uint32_t
> (output.
size ());
143 template <
typename Po
intInT,
typename Po
intOutT>
void
146 const std::vector<int> &nn_indices,
147 std::vector<float> &nn_sqr_dists,
149 NormalCloud &projected_points_normals)
154 Eigen::Vector4f xyz_centroid;
165 Eigen::Vector4f model_coefficients;
166 pcl::eigen33 (covariance_matrix, eigen_value, eigen_vector);
167 model_coefficients.head<3> () = eigen_vector;
168 model_coefficients[3] = 0;
169 model_coefficients[3] = -1 * model_coefficients.dot (xyz_centroid);
172 Eigen::Vector3f point = input[(*indices_)[index]].getVector3fMap ();
173 float distance = point.dot (model_coefficients.head<3> ()) + model_coefficients[3];
174 point -= distance * model_coefficients.head<3> ();
176 float curvature = covariance_matrix.trace ();
179 curvature = fabsf (eigen_value / curvature);
183 Eigen::Vector3d plane_normal = model_coefficients.head<3> ().cast<double> ();
185 Eigen::VectorXd c_vec;
187 Eigen::Vector3d v (0.0f, 0.0f, 0.0f), u (0.0f, 0.0f, 0.0f);
193 if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_)
197 std::vector<Eigen::Vector3d> de_meaned (nn_indices.size ());
198 for (
size_t ni = 0; ni < nn_indices.size (); ++ni)
200 de_meaned[ni][0] = input_->points[nn_indices[ni]].x - point[0];
201 de_meaned[ni][1] = input_->points[nn_indices[ni]].y - point[1];
202 de_meaned[ni][2] = input_->points[nn_indices[ni]].z - point[2];
203 nn_sqr_dists[ni] =
static_cast<float> (de_meaned[ni].dot (de_meaned[ni]));
207 Eigen::VectorXd weight_vec (nn_indices.size ());
208 Eigen::MatrixXd P (nr_coeff_, nn_indices.size ());
209 Eigen::VectorXd f_vec (nn_indices.size ());
210 Eigen::MatrixXd P_weight;
211 Eigen::MatrixXd P_weight_Pt (nr_coeff_, nr_coeff_);
214 v = plane_normal.unitOrthogonal ();
215 u = plane_normal.cross (v);
219 double u_coord, v_coord, u_pow, v_pow;
220 for (
size_t ni = 0; ni < nn_indices.size (); ++ni)
223 weight_vec (ni) = exp (-nn_sqr_dists[ni] / sqr_gauss_param_);
226 u_coord = de_meaned[ni].dot (u);
227 v_coord = de_meaned[ni].dot (v);
228 f_vec (ni) = de_meaned[ni].dot (plane_normal);
233 for (
int ui = 0; ui <= order_; ++ui)
236 for (
int vi = 0; vi <= order_ - ui; ++vi)
238 P (j++, ni) = u_pow * v_pow;
246 P_weight = P * weight_vec.asDiagonal ();
247 P_weight_Pt = P_weight * P.transpose ();
248 c_vec = P_weight * f_vec;
249 P_weight_Pt.llt ().solveInPlace (c_vec);
252 switch (upsample_method_)
256 Eigen::Vector3d normal = plane_normal;
258 if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_ &&
pcl_isfinite (c_vec[0]))
260 point += (c_vec[0] * plane_normal).cast<float> ();
263 if (compute_normals_)
264 normal = plane_normal - c_vec[order_ + 1] * u - c_vec[1] * v;
271 projected_points.push_back (aux);
273 if (compute_normals_)
276 aux_normal.normal_x =
static_cast<float> (normal[0]);
277 aux_normal.normal_y =
static_cast<float> (normal[1]);
278 aux_normal.normal_z =
static_cast<float> (normal[2]);
280 projected_points_normals.push_back (aux_normal);
286 case (SAMPLE_LOCAL_PLANE):
289 for (
float u_disp = -static_cast<float> (upsampling_radius_); u_disp <= upsampling_radius_; u_disp += static_cast<float> (upsampling_step_))
290 for (
float v_disp = -static_cast<float> (upsampling_radius_); v_disp <= upsampling_radius_; v_disp += static_cast<float> (upsampling_step_))
291 if (u_disp*u_disp + v_disp*v_disp < upsampling_radius_*upsampling_radius_)
293 PointOutT projected_point;
295 projectPointToMLSSurface (u_disp, v_disp, u, v, plane_normal, curvature, point, c_vec,
296 static_cast<int> (nn_indices.size ()),
297 projected_point, projected_normal);
299 projected_points.push_back (projected_point);
300 if (compute_normals_)
301 projected_points_normals.push_back (projected_normal);
306 case (RANDOM_UNIFORM_DENSITY):
309 int num_points_to_add =
static_cast<int> (floor (desired_num_points_in_radius_ / 2.0 / static_cast<double> (nn_indices.size ())));
312 if (num_points_to_add <= 0)
315 Eigen::Vector3d normal = plane_normal;
316 if (polynomial_fit_ && static_cast<int> (nn_indices.size ()) >= nr_coeff_ &&
pcl_isfinite (c_vec[0]))
319 point += (c_vec[0] * plane_normal).cast<float> ();
321 if (compute_normals_)
322 normal = plane_normal - c_vec[order_ + 1] * u - c_vec[1] * v;
328 projected_points.push_back (aux);
330 if (compute_normals_)
333 aux_normal.normal_x =
static_cast<float> (normal[0]);
334 aux_normal.normal_y =
static_cast<float> (normal[1]);
335 aux_normal.normal_z =
static_cast<float> (normal[2]);
337 projected_points_normals.push_back (aux_normal);
343 for (
int num_added = 0; num_added < num_points_to_add;)
345 float u_disp = (*rng_uniform_distribution_) (),
346 v_disp = (*rng_uniform_distribution_) ();
348 if (u_disp * u_disp + v_disp * v_disp > search_radius_ * search_radius_/4)
352 PointOutT projected_point;
354 projectPointToMLSSurface (u_disp, v_disp, u, v, plane_normal, curvature, point, c_vec,
355 static_cast<int> (nn_indices.size ()),
356 projected_point, projected_normal);
358 projected_points.push_back (projected_point);
359 if (compute_normals_)
360 projected_points_normals.push_back (projected_normal);
368 case (VOXEL_GRID_DILATION):
372 MLSResult result (plane_normal, u, v, c_vec, static_cast<int> (nn_indices.size ()), curvature);
373 mls_results_[index] = result;
381 template <
typename Po
intInT,
typename Po
intOutT>
void
383 Eigen::Vector3d &u, Eigen::Vector3d &v,
384 Eigen::Vector3d &plane_normal,
386 Eigen::Vector3f &query_point,
387 Eigen::VectorXd &c_vec,
389 PointOutT &result_point,
392 double n_disp = 0.0f;
393 double d_u = 0.0f, d_v = 0.0f;
396 if (polynomial_fit_ && num_neighbors >= 5*nr_coeff_ &&
pcl_isfinite (c_vec[0]))
401 float u_pow = 1.0f, v_pow = 1.0f, u_pow_prev = 1.0f, v_pow_prev = 1.0f;
402 for (
int ui = 0; ui <= order_; ++ui)
405 for (
int vi = 0; vi <= order_ - ui; ++vi)
408 n_disp += u_pow * v_pow * c_vec[j++];
412 d_u += c_vec[j-1] * ui * u_pow_prev * v_pow;
414 d_v += c_vec[j-1] * vi * u_pow * v_pow_prev;
424 Eigen::Vector3d normal = plane_normal - d_u * u - d_v * v;
426 result_point.x =
static_cast<float> (query_point[0] + u[0] * u_disp + v[0] * v_disp + normal[0] * n_disp);
427 result_point.y =
static_cast<float> (query_point[1] + u[1] * u_disp + v[1] * v_disp + normal[1] * n_disp);
428 result_point.z =
static_cast<float> (query_point[2] + u[2] * u_disp + v[2] * v_disp + normal[2] * n_disp);
430 result_normal.normal_x =
static_cast<float> (normal[0]);
431 result_normal.normal_y =
static_cast<float> (normal[1]);
432 result_normal.normal_z =
static_cast<float> (normal[2]);
438 template <
typename Po
intInT,
typename Po
intOutT>
void
442 nr_coeff_ = (order_ + 1) * (order_ + 2) / 2;
446 std::vector<int> nn_indices;
447 std::vector<float> nn_sqr_dists;
450 for (
size_t cp = 0; cp < indices_->size (); ++cp)
453 if (!searchForNeighbors (
int (cp), nn_indices, nn_sqr_dists))
458 if (nn_indices.size () < 3)
463 NormalCloud projected_points_normals;
465 computeMLSPointNormal (
int (cp), *input_, nn_indices, nn_sqr_dists, projected_points, projected_points_normals);
468 output.insert (output.end (), projected_points.begin (), projected_points.end ());
469 if (compute_normals_)
470 normals_->insert (normals_->end (), projected_points_normals.begin (), projected_points_normals.end ());
477 if (upsample_method_ == VOXEL_GRID_DILATION)
479 MLSVoxelGrid voxel_grid (input_, indices_, voxel_size_);
481 for (
int iteration = 0; iteration < dilation_iteration_num_; ++iteration)
482 voxel_grid.dilate ();
485 for (
typename MLSVoxelGrid::HashMap::iterator m_it = voxel_grid.voxel_grid_.begin (); m_it != voxel_grid.voxel_grid_.end (); ++m_it)
489 voxel_grid.getPosition (m_it->first, pos);
496 std::vector<int> nn_indices;
497 std::vector<float> nn_dists;
498 tree_->nearestKSearch (p, 1, nn_indices, nn_dists);
499 int input_index = nn_indices.front ();
503 if (mls_results_[input_index].valid ==
false)
506 Eigen::Vector3f add_point = p.getVector3fMap (),
507 input_point = input_->points[input_index].getVector3fMap ();
509 Eigen::Vector3d aux = mls_results_[input_index].u;
510 Eigen::Vector3f u = aux.cast<
float> ();
511 aux = mls_results_[input_index].v;
512 Eigen::Vector3f v = aux.cast<
float> ();
514 float u_disp = (add_point - input_point).dot (u),
515 v_disp = (add_point - input_point).dot (v);
517 PointOutT result_point;
519 projectPointToMLSSurface (u_disp, v_disp,
520 mls_results_[input_index].u, mls_results_[input_index].v,
521 mls_results_[input_index].plane_normal,
522 mls_results_[input_index].curvature,
524 mls_results_[input_index].c_vec,
525 mls_results_[input_index].num_neighbors,
526 result_point, result_normal);
528 float d_before = (pos - input_point).norm (),
529 d_after = (result_point.getVector3fMap () - input_point). norm();
530 if (d_after > d_before)
533 output.push_back (result_point);
534 if (compute_normals_)
535 normals_->push_back (result_normal);
546 template <
typename Po
intInT,
typename Po
intOutT>
548 Eigen::Vector3d &a_u,
549 Eigen::Vector3d &a_v,
550 Eigen::VectorXd a_c_vec,
552 float &a_curvature) :
553 plane_normal (a_plane_normal), u (a_u), v (a_v), c_vec (a_c_vec), num_neighbors (a_num_neighbors),
554 curvature (a_curvature), valid (true)
559 template <
typename Po
intInT,
typename Po
intOutT>
563 voxel_grid_ (), bounding_min_ (), bounding_max_ (), data_size_ (), voxel_size_ (voxel_size)
567 Eigen::Vector4f bounding_box_size = bounding_max_ - bounding_min_;
568 double max_size = (std::max) ((std::max)(bounding_box_size.x (), bounding_box_size.y ()), bounding_box_size.z ());
570 data_size_ =
static_cast<uint64_t
> (1.5 * max_size / voxel_size_);
571 for (
unsigned int i = 0; i < indices->size (); ++i)
575 getCellIndex (cloud->points[(*indices)[i]].getVector3fMap (), pos);
578 getIndexIn1D (pos, index_1d);
580 voxel_grid_[index_1d] = leaf;
585 template <
typename Po
intInT,
typename Po
intOutT>
void
588 HashMap new_voxel_grid = voxel_grid_;
589 for (
typename MLSVoxelGrid::HashMap::iterator m_it = voxel_grid_.begin (); m_it != voxel_grid_.end (); ++m_it)
591 Eigen::Vector3i index;
592 getIndexIn3D (m_it->first, index);
595 for (
int x = -1; x <= 1; ++x)
596 for (
int y = -1; y <= 1; ++y)
597 for (
int z = -1; z <= 1; ++z)
598 if (x != 0 || y != 0 || z != 0)
600 Eigen::Vector3i new_index;
601 new_index = index + Eigen::Vector3i (x, y, z);
604 getIndexIn1D (new_index, index_1d);
606 new_voxel_grid[index_1d] = leaf;
609 voxel_grid_ = new_voxel_grid;
613 #define PCL_INSTANTIATE_MovingLeastSquares(T,OutT) template class PCL_EXPORTS pcl::MovingLeastSquares<T,OutT>;
615 #endif // PCL_SURFACE_IMPL_MLS_H_