Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
sac_segmentation.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2009, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * $Id: sac_segmentation.hpp 4702 2012-02-23 09:39:33Z gedikli $
00035  *
00036  */
00037 
00038 #ifndef PCL_SEGMENTATION_IMPL_SAC_SEGMENTATION_H_
00039 #define PCL_SEGMENTATION_IMPL_SAC_SEGMENTATION_H_
00040 
00041 #include "pcl/segmentation/sac_segmentation.h"
00042 
00043 // Sample Consensus methods
00044 #include "pcl/sample_consensus/sac.h"
00045 #include "pcl/sample_consensus/lmeds.h"
00046 #include "pcl/sample_consensus/mlesac.h"
00047 #include "pcl/sample_consensus/msac.h"
00048 #include "pcl/sample_consensus/ransac.h"
00049 #include "pcl/sample_consensus/rmsac.h"
00050 #include "pcl/sample_consensus/rransac.h"
00051 #include "pcl/sample_consensus/prosac.h"
00052 
00053 // Sample Consensus models
00054 #include "pcl/sample_consensus/sac_model.h"
00055 #include "pcl/sample_consensus/sac_model_circle.h"
00056 #include "pcl/sample_consensus/sac_model_cylinder.h"
00057 #include "pcl/sample_consensus/sac_model_line.h"
00058 #include "pcl/sample_consensus/sac_model_normal_plane.h"
00059 #include "pcl/sample_consensus/sac_model_parallel_plane.h"
00060 #include "pcl/sample_consensus/sac_model_normal_parallel_plane.h"
00061 #include "pcl/sample_consensus/sac_model_parallel_line.h"
00062 #include "pcl/sample_consensus/sac_model_perpendicular_plane.h"
00063 #include "pcl/sample_consensus/sac_model_plane.h"
00064 #include "pcl/sample_consensus/sac_model_sphere.h"
00065 #include "pcl/sample_consensus/sac_model_stick.h"
00066 
00068 template <typename PointT> void
00069 pcl::SACSegmentation<PointT>::segment (PointIndices &inliers, ModelCoefficients &model_coefficients)
00070 {
00071   // Copy the header information
00072   inliers.header = model_coefficients.header = input_->header;
00073 
00074   if (!initCompute ()) 
00075   {
00076     inliers.indices.clear (); model_coefficients.values.clear ();
00077     return;
00078   }
00079 
00080   // Initialize the Sample Consensus model and set its parameters
00081   if (!initSACModel (model_type_))
00082   {
00083     PCL_ERROR ("[pcl::%s::segment] Error initializing the SAC model!\n", getClassName ().c_str ());
00084     deinitCompute ();
00085     inliers.indices.clear (); model_coefficients.values.clear ();
00086     return;
00087   }
00088   // Initialize the Sample Consensus method and set its parameters
00089   initSAC (method_type_);
00090 
00091   if (!sac_->computeModel (0))
00092   {
00093     PCL_ERROR ("[pcl::%s::segment] Error segmenting the model! No solution found.\n", getClassName ().c_str ());
00094     deinitCompute ();
00095     inliers.indices.clear (); model_coefficients.values.clear ();
00096     return;
00097   }
00098 
00099   // Get the model inliers
00100   sac_->getInliers (inliers.indices);
00101 
00102   // Get the model coefficients
00103   Eigen::VectorXf coeff;
00104   sac_->getModelCoefficients (coeff);
00105 
00106   // If the user needs optimized coefficients
00107   if (optimize_coefficients_)
00108   {
00109     Eigen::VectorXf coeff_refined;
00110     model_->optimizeModelCoefficients (inliers.indices, coeff, coeff_refined);
00111     model_coefficients.values.resize (coeff_refined.size ());
00112     memcpy (&model_coefficients.values[0], &coeff_refined[0], coeff_refined.size () * sizeof (float));
00113     // Refine inliers
00114     model_->selectWithinDistance (coeff_refined, threshold_, inliers.indices);
00115   }
00116   else
00117   {
00118     model_coefficients.values.resize (coeff.size ());
00119     memcpy (&model_coefficients.values[0], &coeff[0], coeff.size () * sizeof (float));
00120   }
00121 
00122   deinitCompute ();
00123 }
00124 
00126 template <typename PointT> bool
00127 pcl::SACSegmentation<PointT>::initSACModel (const int model_type)
00128 {
00129   if (model_)
00130     model_.reset ();
00131 
00132   // Build the model
00133   switch (model_type)
00134   {
00135     case SACMODEL_PLANE:
00136     {
00137       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PLANE\n", getClassName ().c_str ());
00138       model_.reset (new SampleConsensusModelPlane<PointT> (input_, *indices_));
00139       break;
00140     }
00141     case SACMODEL_LINE:
00142     {
00143       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_LINE\n", getClassName ().c_str ());
00144       model_.reset (new SampleConsensusModelLine<PointT> (input_, *indices_));
00145       break;
00146     }
00147     case SACMODEL_STICK:
00148     {
00149       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_STICK\n", getClassName ().c_str ());
00150       model_.reset (new SampleConsensusModelStick<PointT> (input_, *indices_));
00151       double min_radius, max_radius;
00152       model_->getRadiusLimits (min_radius, max_radius);
00153       if (radius_min_ != min_radius && radius_max_ != max_radius)
00154       {
00155         PCL_DEBUG ("[pcl::%s::initSACModel] Setting radius limits to %f/%f\n", getClassName ().c_str (), radius_min_, radius_max_);
00156         model_->setRadiusLimits (radius_min_, radius_max_);
00157       }
00158       break;
00159     }
00160     case SACMODEL_CIRCLE2D:
00161     {
00162       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_CIRCLE2D\n", getClassName ().c_str ());
00163       model_.reset (new SampleConsensusModelCircle2D<PointT> (input_, *indices_));
00164       typename SampleConsensusModelCircle2D<PointT>::Ptr model_circle = boost::static_pointer_cast<SampleConsensusModelCircle2D<PointT> > (model_);
00165       double min_radius, max_radius;
00166       model_circle->getRadiusLimits (min_radius, max_radius);
00167       if (radius_min_ != min_radius && radius_max_ != max_radius)
00168       {
00169         PCL_DEBUG ("[pcl::%s::initSACModel] Setting radius limits to %f/%f\n", getClassName ().c_str (), radius_min_, radius_max_);
00170         model_circle->setRadiusLimits (radius_min_, radius_max_);
00171       }
00172       break;
00173     }
00174     case SACMODEL_SPHERE:
00175     {
00176       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_SPHERE\n", getClassName ().c_str ());
00177       model_.reset (new SampleConsensusModelSphere<PointT> (input_, *indices_));
00178       typename SampleConsensusModelSphere<PointT>::Ptr model_sphere = boost::static_pointer_cast<SampleConsensusModelSphere<PointT> > (model_);
00179       double min_radius, max_radius;
00180       model_sphere->getRadiusLimits (min_radius, max_radius);
00181       if (radius_min_ != min_radius && radius_max_ != max_radius)
00182       {
00183         PCL_DEBUG ("[pcl::%s::initSACModel] Setting radius limits to %f/%f\n", getClassName ().c_str (), radius_min_, radius_max_);
00184         model_sphere->setRadiusLimits (radius_min_, radius_max_);
00185       }
00186       break;
00187     }
00188     case SACMODEL_PARALLEL_LINE:
00189     {
00190       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PARALLEL_LINE\n", getClassName ().c_str ());
00191       model_.reset (new SampleConsensusModelParallelLine<PointT> (input_, *indices_));
00192       typename SampleConsensusModelParallelLine<PointT>::Ptr model_parallel = boost::static_pointer_cast<SampleConsensusModelParallelLine<PointT> > (model_);
00193       if (axis_ != Eigen::Vector3f::Zero () && model_parallel->getAxis () != axis_)
00194       {
00195         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f\n", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00196         model_parallel->setAxis (axis_);
00197       }
00198       if (eps_angle_ != 0.0 && model_parallel->getEpsAngle () != eps_angle_)
00199       {
00200         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)\n", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00201         model_parallel->setEpsAngle (eps_angle_);
00202       }
00203       break;
00204     }
00205     case SACMODEL_PERPENDICULAR_PLANE:
00206     {
00207       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PERPENDICULAR_PLANE\n", getClassName ().c_str ());
00208       model_.reset (new SampleConsensusModelPerpendicularPlane<PointT> (input_, *indices_));
00209       typename SampleConsensusModelPerpendicularPlane<PointT>::Ptr model_perpendicular = boost::static_pointer_cast<SampleConsensusModelPerpendicularPlane<PointT> > (model_);
00210       if (axis_ != Eigen::Vector3f::Zero () && model_perpendicular->getAxis () != axis_)
00211       {
00212         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f\n", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00213         model_perpendicular->setAxis (axis_);
00214       }
00215       if (eps_angle_ != 0.0 && model_perpendicular->getEpsAngle () != eps_angle_)
00216       {
00217         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)\n", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00218         model_perpendicular->setEpsAngle (eps_angle_);
00219       }
00220       break;
00221     }
00222     case SACMODEL_PARALLEL_PLANE:
00223     {
00224       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_PARALLEL_PLANE\n", getClassName ().c_str ());
00225       model_.reset (new SampleConsensusModelParallelPlane<PointT> (input_, *indices_));
00226       typename SampleConsensusModelParallelPlane<PointT>::Ptr model_parallel = boost::static_pointer_cast<SampleConsensusModelParallelPlane<PointT> > (model_);
00227       if (axis_ != Eigen::Vector3f::Zero () && model_parallel->getAxis () != axis_)
00228       {
00229         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f\n", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00230         model_parallel->setAxis (axis_);
00231       }
00232       if (eps_angle_ != 0.0 && model_parallel->getEpsAngle () != eps_angle_)
00233       {
00234         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)\n", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00235         model_parallel->setEpsAngle (eps_angle_);
00236       }
00237       break;
00238     }
00239     default:
00240     {
00241       PCL_ERROR ("[pcl::%s::initSACModel] No valid model given!\n", getClassName ().c_str ());
00242       return (false);
00243     }
00244   }
00245   return (true);
00246 }
00247 
00249 template <typename PointT> void
00250 pcl::SACSegmentation<PointT>::initSAC (const int method_type)
00251 {
00252   if (sac_)
00253     sac_.reset ();
00254   // Build the sample consensus method
00255   switch (method_type)
00256   {
00257     case SAC_RANSAC:
00258     default:
00259     {
00260       PCL_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_RANSAC with a model threshold of %f\n", getClassName ().c_str (), threshold_);
00261       sac_.reset (new RandomSampleConsensus<PointT> (model_, threshold_));
00262       break;
00263     }
00264     case SAC_LMEDS:
00265     {
00266       PCL_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_LMEDS with a model threshold of %f\n", getClassName ().c_str (), threshold_);
00267       sac_.reset (new LeastMedianSquares<PointT> (model_, threshold_));
00268       break;
00269     }
00270     case SAC_MSAC:
00271     {
00272       PCL_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_MSAC with a model threshold of %f\n", getClassName ().c_str (), threshold_);
00273       sac_.reset (new MEstimatorSampleConsensus<PointT> (model_, threshold_));
00274       break;
00275     }
00276     case SAC_RRANSAC:
00277     {
00278       PCL_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_RRANSAC with a model threshold of %f\n", getClassName ().c_str (), threshold_);
00279       sac_.reset (new RandomizedRandomSampleConsensus<PointT> (model_, threshold_));
00280       break;
00281     }
00282     case SAC_RMSAC:
00283     {
00284       PCL_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_RMSAC with a model threshold of %f\n", getClassName ().c_str (), threshold_);
00285       sac_.reset (new RandomizedMEstimatorSampleConsensus<PointT> (model_, threshold_));
00286       break;
00287     }
00288     case SAC_MLESAC:
00289     {
00290       PCL_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_MLESAC with a model threshold of %f\n", getClassName ().c_str (), threshold_);
00291       sac_.reset (new MaximumLikelihoodSampleConsensus<PointT> (model_, threshold_));
00292       break;
00293     }
00294     case SAC_PROSAC:
00295     {
00296       PCL_DEBUG ("[pcl::%s::initSAC] Using a method of type: SAC_PROSAC with a model threshold of %f\n", getClassName ().c_str (), threshold_);
00297       sac_.reset (new ProgressiveSampleConsensus<PointT> (model_, threshold_));
00298       break;
00299     }
00300   }
00301   // Set the Sample Consensus parameters if they are given/changed
00302   if (sac_->getProbability () != probability_)
00303   {
00304     PCL_DEBUG ("[pcl::%s::initSAC] Setting the desired probability to %f\n", getClassName ().c_str (), probability_);
00305     sac_->setProbability (probability_);
00306   }
00307   if (max_iterations_ != -1 && sac_->getMaxIterations () != max_iterations_)
00308   {
00309     PCL_DEBUG ("[pcl::%s::initSAC] Setting the maximum number of iterations to %d\n", getClassName ().c_str (), max_iterations_);
00310     sac_->setMaxIterations (max_iterations_);
00311   }
00312 }
00313 
00315 template <typename PointT, typename PointNT> bool
00316 pcl::SACSegmentationFromNormals<PointT, PointNT>::initSACModel (const int model_type)
00317 {
00318   if (!input_ || !normals_)
00319   {
00320     PCL_ERROR ("[pcl::%s::initSACModel] Input data (XYZ or normals) not given! Cannot continue.\n", getClassName ().c_str ());
00321     return (false);
00322   }
00323   // Check if input is synced with the normals
00324   if (input_->points.size () != normals_->points.size ())
00325   {
00326     PCL_ERROR ("[pcl::%s::initSACModel] The number of points inthe input point cloud differs than the number of points in the normals!\n", getClassName ().c_str ());
00327     return (false);
00328   }
00329 
00330   if (model_)
00331     model_.reset ();
00332 
00333   // Build the model
00334   switch (model_type)
00335   {
00336     case SACMODEL_CYLINDER:
00337     {
00338       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_CYLINDER\n", getClassName ().c_str ());
00339       model_.reset (new SampleConsensusModelCylinder<PointT, PointNT > (input_, *indices_));
00340       typename SampleConsensusModelCylinder<PointT, PointNT>::Ptr model_cylinder = boost::static_pointer_cast<SampleConsensusModelCylinder<PointT, PointNT> > (model_);
00341 
00342       // Set the input normals
00343       model_cylinder->setInputNormals (normals_);
00344       double min_radius, max_radius;
00345       model_cylinder->getRadiusLimits (min_radius, max_radius);
00346       if (radius_min_ != min_radius && radius_max_ != max_radius)
00347       {
00348         PCL_DEBUG ("[pcl::%s::initSACModel] Setting radius limits to %f/%f\n", getClassName ().c_str (), radius_min_, radius_max_);
00349         model_cylinder->setRadiusLimits (radius_min_, radius_max_);
00350       }
00351       if (distance_weight_ != model_cylinder->getNormalDistanceWeight ())
00352       {
00353         PCL_DEBUG ("[pcl::%s::initSACModel] Setting normal distance weight to %f\n", getClassName ().c_str (), distance_weight_);
00354         model_cylinder->setNormalDistanceWeight (distance_weight_);
00355       }
00356       if (axis_ != Eigen::Vector3f::Zero () && model_cylinder->getAxis () != axis_)
00357       {
00358         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f\n", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00359         model_cylinder->setAxis (axis_);
00360       }
00361       if (eps_angle_ != 0.0 && model_cylinder->getEpsAngle () != eps_angle_)
00362       {
00363         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)\n", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00364         model_cylinder->setEpsAngle (eps_angle_);
00365       }
00366       break;
00367     }
00368     case SACMODEL_NORMAL_PLANE:
00369     {
00370       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_NORMAL_PLANE\n", getClassName ().c_str ());
00371       model_.reset (new SampleConsensusModelNormalPlane<PointT, PointNT> (input_, *indices_));
00372       typename SampleConsensusModelNormalPlane<PointT, PointNT>::Ptr model_normals = boost::static_pointer_cast<SampleConsensusModelNormalPlane<PointT, PointNT> > (model_);
00373       // Set the input normals
00374       model_normals->setInputNormals (normals_);
00375       if (distance_weight_ != model_normals->getNormalDistanceWeight ())
00376       {
00377         PCL_DEBUG ("[pcl::%s::initSACModel] Setting normal distance weight to %f\n", getClassName ().c_str (), distance_weight_);
00378         model_normals->setNormalDistanceWeight (distance_weight_);
00379       }
00380       break;
00381     }
00382     case SACMODEL_NORMAL_PARALLEL_PLANE:
00383     {
00384       PCL_DEBUG ("[pcl::%s::initSACModel] Using a model of type: SACMODEL_NORMAL_PARALLEL_PLANE\n", getClassName ().c_str ());
00385       model_.reset (new SampleConsensusModelNormalParallelPlane<PointT, PointNT> (input_, *indices_));
00386       typename SampleConsensusModelNormalParallelPlane<PointT, PointNT>::Ptr model_normals = boost::static_pointer_cast<SampleConsensusModelNormalParallelPlane<PointT, PointNT> > (model_);
00387       // Set the input normals
00388       model_normals->setInputNormals (normals_);
00389       if (distance_weight_ != model_normals->getNormalDistanceWeight ())
00390       {
00391         PCL_DEBUG ("[pcl::%s::initSACModel] Setting normal distance weight to %f\n", getClassName ().c_str (), distance_weight_);
00392         model_normals->setNormalDistanceWeight (distance_weight_);
00393       }
00394       if (distance_from_origin_ != model_normals->getDistanceFromOrigin ())
00395       {
00396         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the distance to origin to %f\n", getClassName ().c_str (), distance_from_origin_);
00397         model_normals->setDistanceFromOrigin (distance_from_origin_);
00398       }
00399       if (axis_ != Eigen::Vector3f::Zero () && model_normals->getAxis () != axis_)
00400       {
00401         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the axis to %f, %f, %f\n", getClassName ().c_str (), axis_[0], axis_[1], axis_[2]);
00402         model_normals->setAxis (axis_);
00403       }
00404       if (eps_angle_ != 0.0 && model_normals->getEpsAngle () != eps_angle_)
00405       {
00406         PCL_DEBUG ("[pcl::%s::initSACModel] Setting the epsilon angle to %f (%f degrees)\n", getClassName ().c_str (), eps_angle_, eps_angle_ * 180.0 / M_PI);
00407         model_normals->setEpsAngle (eps_angle_);
00408       }
00409       break;
00410     }
00411     // If nothing else, try SACSegmentation
00412     default:
00413     {
00414       return (pcl::SACSegmentation<PointT>::initSACModel (model_type));
00415     }
00416   }
00417   return (true);
00418 }
00419 
00420 #define PCL_INSTANTIATE_SACSegmentation(T) template class PCL_EXPORTS pcl::SACSegmentation<T>;
00421 #define PCL_INSTANTIATE_SACSegmentationFromNormals(T,NT) template class PCL_EXPORTS pcl::SACSegmentationFromNormals<T,NT>;
00422 
00423 #endif        // PCL_SEGMENTATION_IMPL_SAC_SEGMENTATION_H_
00424