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 #ifndef PCL_VOXEL_GRID_COVARIANCE_H_
00039 #define PCL_VOXEL_GRID_COVARIANCE_H_
00040
00041 #include <pcl/filters/boost.h>
00042 #include <pcl/filters/voxel_grid.h>
00043 #include <map>
00044 #include <pcl/point_types.h>
00045 #include <pcl/kdtree/kdtree_flann.h>
00046
00047 namespace pcl
00048 {
00056 template<typename PointT>
00057 class VoxelGridCovariance : public VoxelGrid<PointT>
00058 {
00059 protected:
00060 using VoxelGrid<PointT>::filter_name_;
00061 using VoxelGrid<PointT>::getClassName;
00062 using VoxelGrid<PointT>::input_;
00063 using VoxelGrid<PointT>::indices_;
00064 using VoxelGrid<PointT>::filter_limit_negative_;
00065 using VoxelGrid<PointT>::filter_limit_min_;
00066 using VoxelGrid<PointT>::filter_limit_max_;
00067 using VoxelGrid<PointT>::filter_field_name_;
00068
00069 using VoxelGrid<PointT>::downsample_all_data_;
00070 using VoxelGrid<PointT>::leaf_layout_;
00071 using VoxelGrid<PointT>::save_leaf_layout_;
00072 using VoxelGrid<PointT>::leaf_size_;
00073 using VoxelGrid<PointT>::min_b_;
00074 using VoxelGrid<PointT>::max_b_;
00075 using VoxelGrid<PointT>::inverse_leaf_size_;
00076 using VoxelGrid<PointT>::div_b_;
00077 using VoxelGrid<PointT>::divb_mul_;
00078
00079
00080 typedef typename pcl::traits::fieldList<PointT>::type FieldList;
00081 typedef typename Filter<PointT>::PointCloud PointCloud;
00082 typedef typename PointCloud::Ptr PointCloudPtr;
00083 typedef typename PointCloud::ConstPtr PointCloudConstPtr;
00084
00085 public:
00086
00087 typedef boost::shared_ptr< VoxelGrid<PointT> > Ptr;
00088 typedef boost::shared_ptr< const VoxelGrid<PointT> > ConstPtr;
00089
00090
00093 struct Leaf
00094 {
00098 Leaf () :
00099 nr_points (0),
00100 mean_ (Eigen::Vector3d::Zero ()),
00101 centroid (),
00102 cov_ (Eigen::Matrix3d::Identity ()),
00103 icov_ (Eigen::Matrix3d::Zero ()),
00104 evecs_ (Eigen::Matrix3d::Identity ()),
00105 evals_ (Eigen::Vector3d::Zero ())
00106 {
00107 }
00108
00112 Eigen::Matrix3d
00113 getCov () const
00114 {
00115 return (cov_);
00116 }
00117
00121 Eigen::Matrix3d
00122 getInverseCov () const
00123 {
00124 return (icov_);
00125 }
00126
00130 Eigen::Vector3d
00131 getMean () const
00132 {
00133 return (mean_);
00134 }
00135
00140 Eigen::Matrix3d
00141 getEvecs () const
00142 {
00143 return (evecs_);
00144 }
00145
00150 Eigen::Vector3d
00151 getEvals () const
00152 {
00153 return (evals_);
00154 }
00155
00159 int
00160 getPointCount () const
00161 {
00162 return (nr_points);
00163 }
00164
00166 int nr_points;
00167
00169 Eigen::Vector3d mean_;
00170
00174 Eigen::VectorXf centroid;
00175
00177 Eigen::Matrix3d cov_;
00178
00180 Eigen::Matrix3d icov_;
00181
00183 Eigen::Matrix3d evecs_;
00184
00186 Eigen::Vector3d evals_;
00187
00188 };
00189
00191 typedef Leaf* LeafPtr;
00192
00194 typedef const Leaf* LeafConstPtr;
00195
00196 public:
00197
00201 VoxelGridCovariance () :
00202 searchable_ (true),
00203 min_points_per_voxel_ (6),
00204 min_covar_eigvalue_mult_ (0.01),
00205 leaves_ (),
00206 voxel_centroids_ (),
00207 voxel_centroids_leaf_indices_ (),
00208 kdtree_ ()
00209 {
00210 downsample_all_data_ = false;
00211 save_leaf_layout_ = false;
00212 leaf_size_.setZero ();
00213 min_b_.setZero ();
00214 max_b_.setZero ();
00215 filter_name_ = "VoxelGridCovariance";
00216 }
00217
00221 inline void
00222 setMinPointPerVoxel (int min_points_per_voxel)
00223 {
00224 if(min_points_per_voxel > 2)
00225 {
00226 min_points_per_voxel_ = min_points_per_voxel;
00227 }
00228 else
00229 {
00230 PCL_WARN ("%s: Covariance calculation requires at least 3 points, setting Min Point per Voxel to 3 ", this->getClassName ().c_str ());
00231 min_points_per_voxel_ = 3;
00232 }
00233 }
00234
00238 inline int
00239 getMinPointPerVoxel ()
00240 {
00241 return min_points_per_voxel_;
00242 }
00243
00247 inline void
00248 setCovEigValueInflationRatio (double min_covar_eigvalue_mult)
00249 {
00250 min_covar_eigvalue_mult_ = min_covar_eigvalue_mult;
00251 }
00252
00256 inline double
00257 getCovEigValueInflationRatio ()
00258 {
00259 return min_covar_eigvalue_mult_;
00260 }
00261
00266 inline void
00267 filter (PointCloud &output, bool searchable = false)
00268 {
00269 searchable_ = searchable;
00270 applyFilter (output);
00271
00272 voxel_centroids_ = PointCloudPtr (new PointCloud (output));
00273
00274 if (searchable_ && voxel_centroids_->size() > 0)
00275 {
00276
00277 kdtree_.setInputCloud (voxel_centroids_);
00278 }
00279 }
00280
00284 inline void
00285 filter (bool searchable = false)
00286 {
00287 searchable_ = searchable;
00288 voxel_centroids_ = PointCloudPtr (new PointCloud);
00289 applyFilter (*voxel_centroids_);
00290
00291 if (searchable_ && voxel_centroids_->size() > 0)
00292 {
00293
00294 kdtree_.setInputCloud (voxel_centroids_);
00295 }
00296 }
00297
00302 inline LeafConstPtr
00303 getLeaf (int index)
00304 {
00305 typename std::map<size_t, Leaf>::iterator leaf_iter = leaves_.find (index);
00306 if (leaf_iter != leaves_.end ())
00307 {
00308 LeafConstPtr ret (&(leaf_iter->second));
00309 return ret;
00310 }
00311 else
00312 return NULL;
00313 }
00314
00319 inline LeafConstPtr
00320 getLeaf (PointT &p)
00321 {
00322
00323 int ijk0 = static_cast<int> (floor (p.x * inverse_leaf_size_[0]) - min_b_[0]);
00324 int ijk1 = static_cast<int> (floor (p.y * inverse_leaf_size_[1]) - min_b_[1]);
00325 int ijk2 = static_cast<int> (floor (p.z * inverse_leaf_size_[2]) - min_b_[2]);
00326
00327
00328 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
00329
00330
00331 typename std::map<size_t, Leaf>::iterator leaf_iter = leaves_.find (idx);
00332 if (leaf_iter != leaves_.end ())
00333 {
00334
00335 LeafConstPtr ret (&(leaf_iter->second));
00336 return ret;
00337 }
00338 else
00339 return NULL;
00340 }
00341
00346 inline LeafConstPtr
00347 getLeaf (Eigen::Vector3f &p)
00348 {
00349
00350 int ijk0 = static_cast<int> (floor (p[0] * inverse_leaf_size_[0]) - min_b_[0]);
00351 int ijk1 = static_cast<int> (floor (p[1] * inverse_leaf_size_[1]) - min_b_[1]);
00352 int ijk2 = static_cast<int> (floor (p[2] * inverse_leaf_size_[2]) - min_b_[2]);
00353
00354
00355 int idx = ijk0 * divb_mul_[0] + ijk1 * divb_mul_[1] + ijk2 * divb_mul_[2];
00356
00357
00358 typename std::map<size_t, Leaf>::iterator leaf_iter = leaves_.find (idx);
00359 if (leaf_iter != leaves_.end ())
00360 {
00361
00362 LeafConstPtr ret (&(leaf_iter->second));
00363 return ret;
00364 }
00365 else
00366 return NULL;
00367
00368 }
00369
00376 int
00377 getNeighborhoodAtPoint (const PointT& reference_point, std::vector<LeafConstPtr> &neighbors);
00378
00382 inline const std::map<size_t, Leaf>&
00383 getLeaves ()
00384 {
00385 return leaves_;
00386 }
00387
00392 inline PointCloudPtr
00393 getCentroids ()
00394 {
00395 return voxel_centroids_;
00396 }
00397
00398
00402 void
00403 getDisplayCloud (pcl::PointCloud<PointXYZ>& cell_cloud);
00404
00413 int
00414 nearestKSearch (const PointT &point, int k,
00415 std::vector<LeafConstPtr> &k_leaves, std::vector<float> &k_sqr_distances)
00416 {
00417 k_leaves.clear ();
00418
00419
00420 if (!searchable_)
00421 {
00422 PCL_WARN ("%s: Not Searchable", this->getClassName ().c_str ());
00423 return 0;
00424 }
00425
00426
00427 std::vector<int> k_indices;
00428 k = kdtree_.nearestKSearch (point, k, k_indices, k_sqr_distances);
00429
00430
00431 k_leaves.reserve (k);
00432 for (std::vector<int>::iterator iter = k_indices.begin (); iter != k_indices.end (); iter++)
00433 {
00434 k_leaves.push_back (&leaves_[voxel_centroids_leaf_indices_[*iter]]);
00435 }
00436 return k;
00437 }
00438
00447 inline int
00448 nearestKSearch (const PointCloud &cloud, int index, int k,
00449 std::vector<LeafConstPtr> &k_leaves, std::vector<float> &k_sqr_distances)
00450 {
00451 if (index >= static_cast<int> (cloud.points.size ()) || index < 0)
00452 return (0);
00453 return (nearestKSearch (cloud.points[index], k, k_leaves, k_sqr_distances));
00454 }
00455
00456
00465 int
00466 radiusSearch (const PointT &point, double radius, std::vector<LeafConstPtr> &k_leaves,
00467 std::vector<float> &k_sqr_distances, unsigned int max_nn = 0)
00468 {
00469 k_leaves.clear ();
00470
00471
00472 if (!searchable_)
00473 {
00474 PCL_WARN ("%s: Not Searchable", this->getClassName ().c_str ());
00475 return 0;
00476 }
00477
00478
00479 std::vector<int> k_indices;
00480 int k = kdtree_.radiusSearch (point, radius, k_indices, k_sqr_distances, max_nn);
00481
00482
00483 k_leaves.reserve (k);
00484 for (std::vector<int>::iterator iter = k_indices.begin (); iter != k_indices.end (); iter++)
00485 {
00486 k_leaves.push_back (&leaves_[voxel_centroids_leaf_indices_[*iter]]);
00487 }
00488 return k;
00489 }
00490
00500 inline int
00501 radiusSearch (const PointCloud &cloud, int index, double radius,
00502 std::vector<LeafConstPtr> &k_leaves, std::vector<float> &k_sqr_distances,
00503 unsigned int max_nn = 0)
00504 {
00505 if (index >= static_cast<int> (cloud.points.size ()) || index < 0)
00506 return (0);
00507 return (radiusSearch (cloud.points[index], radius, k_leaves, k_sqr_distances, max_nn));
00508 }
00509
00510 protected:
00511
00515 void applyFilter (PointCloud &output);
00516
00518 bool searchable_;
00519
00521 int min_points_per_voxel_;
00522
00524 double min_covar_eigvalue_mult_;
00525
00527 std::map<size_t, Leaf> leaves_;
00528
00530 PointCloudPtr voxel_centroids_;
00531
00533 std::vector<int> voxel_centroids_leaf_indices_;
00534
00536 KdTreeFLANN<PointT> kdtree_;
00537 };
00538 }
00539
00540 #ifdef PCL_NO_PRECOMPILE
00541 #include <pcl/filters/impl/voxel_grid_covariance.hpp>
00542 #endif
00543
00544 #endif //#ifndef PCL_VOXEL_GRID_COVARIANCE_H_