00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifndef PCL_MLS_H_
00041 #define PCL_MLS_H_
00042
00043
00044 #include <pcl/pcl_base.h>
00045 #include <boost/bind.hpp>
00046 #include <boost/function.hpp>
00047 #include <boost/random.hpp>
00048 #include <pcl/search/pcl_search.h>
00049 #include <pcl/common/common.h>
00050 #include <pcl/surface/processing.h>
00051
00052 #include <Eigen/SVD>
00053
00054 namespace pcl
00055 {
00065 template <typename PointInT, typename PointOutT>
00066 class MovingLeastSquares: public CloudSurfaceProcessing<PointInT, PointOutT>
00067 {
00068 public:
00069 using PCLBase<PointInT>::input_;
00070 using PCLBase<PointInT>::indices_;
00071 using PCLBase<PointInT>::fake_indices_;
00072 using PCLBase<PointInT>::initCompute;
00073 using PCLBase<PointInT>::deinitCompute;
00074
00075 typedef typename pcl::search::Search<PointInT> KdTree;
00076 typedef typename pcl::search::Search<PointInT>::Ptr KdTreePtr;
00077 typedef pcl::PointCloud<pcl::Normal> NormalCloud;
00078 typedef pcl::PointCloud<pcl::Normal>::Ptr NormalCloudPtr;
00079
00080 typedef pcl::PointCloud<PointOutT> PointCloudOut;
00081 typedef typename PointCloudOut::Ptr PointCloudOutPtr;
00082 typedef typename PointCloudOut::ConstPtr PointCloudOutConstPtr;
00083
00084 typedef pcl::PointCloud<PointInT> PointCloudIn;
00085 typedef typename PointCloudIn::Ptr PointCloudInPtr;
00086 typedef typename PointCloudIn::ConstPtr PointCloudInConstPtr;
00087
00088 typedef boost::function<int (int, double, std::vector<int> &, std::vector<float> &)> SearchMethod;
00089
00090 enum UpsamplingMethod { NONE, SAMPLE_LOCAL_PLANE, RANDOM_UNIFORM_DENSITY, VOXEL_GRID_DILATION };
00091
00093 MovingLeastSquares () : CloudSurfaceProcessing<PointInT, PointOutT> (),
00094 normals_ (),
00095 search_method_ (),
00096 tree_ (),
00097 order_ (2),
00098 polynomial_fit_ (true),
00099 search_radius_ (0.0),
00100 sqr_gauss_param_ (0.0),
00101 compute_normals_ (false),
00102 upsample_method_ (NONE),
00103 upsampling_radius_ (0.0),
00104 upsampling_step_ (0.0),
00105 rng_uniform_distribution_ (),
00106 desired_num_points_in_radius_ (0),
00107 mls_results_ (),
00108 voxel_size_ (1.0),
00109 dilation_iteration_num_ (0),
00110 nr_coeff_ ()
00111 {};
00112
00113
00117 inline void
00118 setComputeNormals (bool compute_normals) { compute_normals_ = compute_normals; }
00119
00123 inline void
00124 setSearchMethod (const KdTreePtr &tree)
00125 {
00126 tree_ = tree;
00127
00128 int (KdTree::*radiusSearch)(int index, double radius, std::vector<int> &k_indices, std::vector<float> &k_sqr_distances, unsigned int max_nn) const = &KdTree::radiusSearch;
00129 search_method_ = boost::bind (radiusSearch, boost::ref (tree_), _1, _2, _3, _4, 0);
00130 }
00131
00133 inline KdTreePtr
00134 getSearchMethod () { return (tree_); }
00135
00139 inline void
00140 setPolynomialOrder (int order) { order_ = order; }
00141
00143 inline int
00144 getPolynomialOrder () { return (order_); }
00145
00149 inline void
00150 setPolynomialFit (bool polynomial_fit) { polynomial_fit_ = polynomial_fit; }
00151
00153 inline bool
00154 getPolynomialFit () { return (polynomial_fit_); }
00155
00160 inline void
00161 setSearchRadius (double radius) { search_radius_ = radius; sqr_gauss_param_ = search_radius_ * search_radius_; }
00162
00164 inline double
00165 getSearchRadius () { return (search_radius_); }
00166
00171 inline void
00172 setSqrGaussParam (double sqr_gauss_param) { sqr_gauss_param_ = sqr_gauss_param; }
00173
00175 inline double
00176 getSqrGaussParam () const { return (sqr_gauss_param_); }
00177
00194 inline void
00195 setUpsamplingMethod (UpsamplingMethod method) { upsample_method_ = method; }
00196
00197
00202 inline void
00203 setUpsamplingRadius (double radius) { upsampling_radius_ = radius; }
00204
00208 inline double
00209 getUpsamplingRadius () { return upsampling_radius_; }
00210
00215 inline void
00216 setUpsamplingStepSize (double step_size) { upsampling_step_ = step_size; }
00217
00218
00222 inline double
00223 getUpsamplingStepSize () { return upsampling_step_; }
00224
00230 inline void
00231 setPointDensity (int desired_num_points_in_radius) { desired_num_points_in_radius_ = desired_num_points_in_radius; }
00232
00233
00237 inline int
00238 getPointDensity () { return desired_num_points_in_radius_; }
00239
00244 inline void
00245 setDilationVoxelSize (float voxel_size) { voxel_size_ = voxel_size; }
00246
00247
00251 inline float
00252 getDilationVoxelSize () { return voxel_size_; }
00253
00258 inline void
00259 setDilationIterations (int iterations) { dilation_iteration_num_ = iterations; }
00260
00264 inline int
00265 getDilationIterations () { return dilation_iteration_num_; }
00266
00270 void
00271 process (PointCloudOut &output);
00272
00273 protected:
00275 NormalCloudPtr normals_;
00276
00278 SearchMethod search_method_;
00279
00281 KdTreePtr tree_;
00282
00284 int order_;
00285
00287 bool polynomial_fit_;
00288
00290 double search_radius_;
00291
00293 double sqr_gauss_param_;
00294
00296 bool compute_normals_;
00297
00299 UpsamplingMethod upsample_method_;
00300
00304 double upsampling_radius_;
00305
00309 double upsampling_step_;
00310
00314 boost::variate_generator<boost::mt19937, boost::uniform_real<float> > *rng_uniform_distribution_;
00315
00319 int desired_num_points_in_radius_;
00320
00321
00325 struct MLSResult
00326 {
00327 MLSResult () : plane_normal (), u (), v (), c_vec (), num_neighbors (), curvature (), valid (false) {}
00328
00329 MLSResult (Eigen::Vector3d &a_plane_normal,
00330 Eigen::Vector3d &a_u,
00331 Eigen::Vector3d &a_v,
00332 Eigen::VectorXd a_c_vec,
00333 int a_num_neighbors,
00334 float &a_curvature);
00335
00336 Eigen::Vector3d plane_normal, u, v;
00337 Eigen::VectorXd c_vec;
00338 int num_neighbors;
00339 float curvature;
00340 bool valid;
00341 };
00342
00346 std::vector<MLSResult> mls_results_;
00347
00348
00352 class MLSVoxelGrid
00353 {
00354 public:
00355 struct Leaf { Leaf () : valid (true) {} bool valid; };
00356
00357 MLSVoxelGrid (PointCloudInConstPtr& cloud,
00358 IndicesPtr &indices,
00359 float voxel_size);
00360
00361 void
00362 dilate ();
00363
00364 inline void
00365 getIndexIn1D (const Eigen::Vector3i &index, uint64_t &index_1d) const
00366 {
00367 index_1d = index[0] * data_size_ * data_size_ +
00368 index[1] * data_size_ + index[2];
00369 }
00370
00371 inline void
00372 getIndexIn3D (uint64_t index_1d, Eigen::Vector3i& index_3d) const
00373 {
00374 index_3d[0] = static_cast<Eigen::Vector3i::Scalar> (index_1d / (data_size_ * data_size_));
00375 index_1d -= index_3d[0] * data_size_ * data_size_;
00376 index_3d[1] = static_cast<Eigen::Vector3i::Scalar> (index_1d / data_size_);
00377 index_1d -= index_3d[1] * data_size_;
00378 index_3d[2] = static_cast<Eigen::Vector3i::Scalar> (index_1d);
00379 }
00380
00381 inline void
00382 getCellIndex (const Eigen::Vector3f &p, Eigen::Vector3i& index) const
00383 {
00384 for (int i = 0; i < 3; ++i)
00385 index[i] = static_cast<Eigen::Vector3i::Scalar> ((p[i] - bounding_min_(i)) / voxel_size_);
00386 }
00387
00388 inline void
00389 getPosition (const uint64_t &index_1d, Eigen::Vector3f &point) const
00390 {
00391 Eigen::Vector3i index_3d;
00392 getIndexIn3D (index_1d, index_3d);
00393 for (int i = 0; i < 3; ++i)
00394 point[i] = static_cast<Eigen::Vector3f::Scalar> (index_3d[i]) * voxel_size_ + bounding_min_[i];
00395 }
00396
00397 typedef std::map<uint64_t, Leaf> HashMap;
00398 HashMap voxel_grid_;
00399 Eigen::Vector4f bounding_min_, bounding_max_;
00400 uint64_t data_size_;
00401 float voxel_size_;
00402 };
00403
00404
00406 float voxel_size_;
00407
00409 int dilation_iteration_num_;
00410
00412 int nr_coeff_;
00413
00419 inline int
00420 searchForNeighbors (int index, std::vector<int> &indices, std::vector<float> &sqr_distances)
00421 {
00422 return (search_method_ (index, search_radius_, indices, sqr_distances));
00423 }
00424
00435 void
00436 computeMLSPointNormal (int index,
00437 const PointCloudIn &input,
00438 const std::vector<int> &nn_indices,
00439 std::vector<float> &nn_sqr_dists,
00440 PointCloudOut &projected_points,
00441 NormalCloud &projected_points_normals);
00442
00457 void
00458 projectPointToMLSSurface (float &u_disp, float &v_disp,
00459 Eigen::Vector3d &u, Eigen::Vector3d &v,
00460 Eigen::Vector3d &plane_normal,
00461 float &curvature,
00462 Eigen::Vector3f &query_point,
00463 Eigen::VectorXd &c_vec,
00464 int num_neighbors,
00465 PointOutT &result_point,
00466 pcl::Normal &result_normal);
00467
00468 private:
00472 virtual void performProcessing (PointCloudOut &output);
00473
00475 std::string getClassName () const { return ("MovingLeastSquares"); }
00476
00477 public:
00478 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00479 };
00480 }
00481
00482 #endif