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 #ifndef PCL_INTEGRALIMAGE_BASED_NORMAL_ESTIMATOR_H_
00040 #define PCL_INTEGRALIMAGE_BASED_NORMAL_ESTIMATOR_H_
00041
00042 #include <pcl/point_cloud.h>
00043 #include <pcl/point_types.h>
00044 #include <pcl/features/feature.h>
00045 #include <pcl/features/integral_image2D.h>
00046
00047 #if defined BUILD_Maintainer && defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ > 3
00048 #pragma GCC diagnostic ignored "-Weffc++"
00049 #endif
00050 namespace pcl
00051 {
00055 template <typename PointInT, typename PointOutT>
00056 class IntegralImageNormalEstimation: public Feature<PointInT, PointOutT>
00057 {
00058 using Feature<PointInT, PointOutT>::input_;
00059 using Feature<PointInT, PointOutT>::feature_name_;
00060 using Feature<PointInT, PointOutT>::tree_;
00061 using Feature<PointInT, PointOutT>::k_;
00062
00063 public:
00064 typedef boost::shared_ptr<IntegralImageNormalEstimation<PointInT, PointOutT> > Ptr;
00065 typedef boost::shared_ptr<const IntegralImageNormalEstimation<PointInT, PointOutT> > ConstPtr;
00066
00068 enum BorderPolicy
00069 {
00070 BORDER_POLICY_IGNORE,
00071 BORDER_POLICY_MIRROR
00072 };
00073
00085 enum NormalEstimationMethod
00086 {
00087 COVARIANCE_MATRIX,
00088 AVERAGE_3D_GRADIENT,
00089 AVERAGE_DEPTH_CHANGE,
00090 SIMPLE_3D_GRADIENT
00091 };
00092
00093 typedef typename Feature<PointInT, PointOutT>::PointCloudIn PointCloudIn;
00094 typedef typename Feature<PointInT, PointOutT>::PointCloudOut PointCloudOut;
00095
00097 IntegralImageNormalEstimation ()
00098 : normal_estimation_method_(AVERAGE_3D_GRADIENT)
00099 , border_policy_ (BORDER_POLICY_IGNORE)
00100 , rect_width_ (0), rect_width_2_ (0), rect_width_4_ (0)
00101 , rect_height_ (0), rect_height_2_ (0), rect_height_4_ (0)
00102 , distance_threshold_ (0)
00103 , integral_image_DX_ (false)
00104 , integral_image_DY_ (false)
00105 , integral_image_depth_ (false)
00106 , integral_image_XYZ_ (true)
00107 , diff_x_ (NULL)
00108 , diff_y_ (NULL)
00109 , depth_data_ (NULL)
00110 , distance_map_ (NULL)
00111 , use_depth_dependent_smoothing_ (false)
00112 , max_depth_change_factor_ (20.0f*0.001f)
00113 , normal_smoothing_size_ (10.0f)
00114 , init_covariance_matrix_ (false)
00115 , init_average_3d_gradient_ (false)
00116 , init_simple_3d_gradient_ (false)
00117 , init_depth_change_ (false)
00118 , vpx_ (0.0f)
00119 , vpy_ (0.0f)
00120 , vpz_ (0.0f)
00121 , use_sensor_origin_ (true)
00122 {
00123 feature_name_ = "IntegralImagesNormalEstimation";
00124 tree_.reset ();
00125 k_ = 1;
00126 }
00127
00129 virtual ~IntegralImageNormalEstimation ();
00130
00135 void
00136 setRectSize (const int width, const int height);
00137
00141 void
00142 setBorderPolicy (const BorderPolicy border_policy)
00143 {
00144 border_policy_ = border_policy;
00145 }
00146
00153 void
00154 computePointNormal (const int pos_x, const int pos_y, const unsigned point_index, PointOutT &normal);
00155
00162 void
00163 computePointNormalMirror (const int pos_x, const int pos_y, const unsigned point_index, PointOutT &normal);
00164
00169 void
00170 setMaxDepthChangeFactor (float max_depth_change_factor)
00171 {
00172 max_depth_change_factor_ = max_depth_change_factor;
00173 }
00174
00179 void
00180 setNormalSmoothingSize (float normal_smoothing_size)
00181 {
00182 if (normal_smoothing_size <= 0)
00183 {
00184 PCL_ERROR ("[pcl::%s::setNormalSmoothingSize] Invalid normal smoothing size given! (%f). Allowed ranges are: 0 < N. Defaulting to %f.\n",
00185 feature_name_.c_str (), normal_smoothing_size, normal_smoothing_size_);
00186 return;
00187 }
00188 normal_smoothing_size_ = normal_smoothing_size;
00189 }
00190
00203 void
00204 setNormalEstimationMethod (NormalEstimationMethod normal_estimation_method)
00205 {
00206 normal_estimation_method_ = normal_estimation_method;
00207 }
00208
00212 void
00213 setDepthDependentSmoothing (bool use_depth_dependent_smoothing)
00214 {
00215 use_depth_dependent_smoothing_ = use_depth_dependent_smoothing;
00216 }
00217
00221 virtual inline void
00222 setInputCloud (const typename PointCloudIn::ConstPtr &cloud)
00223 {
00224 input_ = cloud;
00225 if (!cloud->isOrganized ())
00226 {
00227 PCL_ERROR ("[pcl::IntegralImageNormalEstimation::setInputCloud] Input dataset is not organized (height = 1).\n");
00228 return;
00229 }
00230
00231 init_covariance_matrix_ = init_average_3d_gradient_ = init_depth_change_ = false;
00232
00233 if (use_sensor_origin_)
00234 {
00235 vpx_ = input_->sensor_origin_.coeff (0);
00236 vpy_ = input_->sensor_origin_.coeff (1);
00237 vpz_ = input_->sensor_origin_.coeff (2);
00238 }
00239
00240
00241 initData ();
00242 }
00243
00246 inline float*
00247 getDistanceMap ()
00248 {
00249 return (distance_map_);
00250 }
00251
00257 inline void
00258 setViewPoint (float vpx, float vpy, float vpz)
00259 {
00260 vpx_ = vpx;
00261 vpy_ = vpy;
00262 vpz_ = vpz;
00263 use_sensor_origin_ = false;
00264 }
00265
00274 inline void
00275 getViewPoint (float &vpx, float &vpy, float &vpz)
00276 {
00277 vpx = vpx_;
00278 vpy = vpy_;
00279 vpz = vpz_;
00280 }
00281
00286 inline void
00287 useSensorOriginAsViewPoint ()
00288 {
00289 use_sensor_origin_ = true;
00290 if (input_)
00291 {
00292 vpx_ = input_->sensor_origin_.coeff (0);
00293 vpy_ = input_->sensor_origin_.coeff (1);
00294 vpz_ = input_->sensor_origin_.coeff (2);
00295 }
00296 else
00297 {
00298 vpx_ = 0;
00299 vpy_ = 0;
00300 vpz_ = 0;
00301 }
00302 }
00303
00304 protected:
00305
00309 void
00310 computeFeature (PointCloudOut &output);
00311
00313 void
00314 initData ();
00315
00316 private:
00317
00328 inline void
00329 flipNormalTowardsViewpoint (const PointInT &point,
00330 float vp_x, float vp_y, float vp_z,
00331 float &nx, float &ny, float &nz)
00332 {
00333
00334 vp_x -= point.x;
00335 vp_y -= point.y;
00336 vp_z -= point.z;
00337
00338
00339 float cos_theta = (vp_x * nx + vp_y * ny + vp_z * nz);
00340
00341
00342 if (cos_theta < 0)
00343 {
00344 nx *= -1;
00345 ny *= -1;
00346 nz *= -1;
00347 }
00348 }
00349
00356 NormalEstimationMethod normal_estimation_method_;
00357
00359 BorderPolicy border_policy_;
00360
00362 int rect_width_;
00363 int rect_width_2_;
00364 int rect_width_4_;
00366 int rect_height_;
00367 int rect_height_2_;
00368 int rect_height_4_;
00369
00371 float distance_threshold_;
00372
00374 IntegralImage2D<float, 3> integral_image_DX_;
00376 IntegralImage2D<float, 3> integral_image_DY_;
00378 IntegralImage2D<float, 1> integral_image_depth_;
00380 IntegralImage2D<float, 3> integral_image_XYZ_;
00381
00383 float *diff_x_;
00385 float *diff_y_;
00386
00388 float *depth_data_;
00389
00391 float *distance_map_;
00392
00394 bool use_depth_dependent_smoothing_;
00395
00397 float max_depth_change_factor_;
00398
00400 float normal_smoothing_size_;
00401
00403 bool init_covariance_matrix_;
00404
00406 bool init_average_3d_gradient_;
00407
00409 bool init_simple_3d_gradient_;
00410
00412 bool init_depth_change_;
00413
00416 float vpx_, vpy_, vpz_;
00417
00419 bool use_sensor_origin_;
00420
00422 bool
00423 initCompute ();
00424
00426 void
00427 initCovarianceMatrixMethod ();
00428
00430 void
00431 initAverage3DGradientMethod ();
00432
00434 void
00435 initAverageDepthChangeMethod ();
00436
00438 void
00439 initSimple3DGradientMethod ();
00440
00441 public:
00442 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
00443 };
00444 }
00445 #if defined BUILD_Maintainer && defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ > 3
00446 #pragma GCC diagnostic warning "-Weffc++"
00447 #endif
00448
00449 #ifdef PCL_NO_PRECOMPILE
00450 #include <pcl/features/impl/integral_image_normal.hpp>
00451 #endif
00452
00453 #endif
00454