Go to the documentation of this file.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
00041 #ifndef PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_
00042 #define PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_
00043
00044 #include <pcl/sample_consensus/mlesac.h>
00045 #include <pcl/point_types.h>
00046
00048 template <typename PointT> bool
00049 pcl::MaximumLikelihoodSampleConsensus<PointT>::computeModel (int debug_verbosity_level)
00050 {
00051
00052 if (threshold_ == std::numeric_limits<double>::max())
00053 {
00054 PCL_ERROR ("[pcl::MaximumLikelihoodSampleConsensus::computeModel] No threshold set!\n");
00055 return (false);
00056 }
00057
00058 iterations_ = 0;
00059 double d_best_penalty = std::numeric_limits<double>::max();
00060 double k = 1.0;
00061
00062 std::vector<int> best_model;
00063 std::vector<int> selection;
00064 Eigen::VectorXf model_coefficients;
00065 std::vector<double> distances;
00066
00067
00068 sigma_ = computeMedianAbsoluteDeviation (sac_model_->getInputCloud (), sac_model_->getIndices (), threshold_);
00069 if (debug_verbosity_level > 1)
00070 PCL_DEBUG ("[pcl::MaximumLikelihoodSampleConsensus::computeModel] Estimated sigma value: %f.\n", sigma_);
00071
00072
00073 Eigen::Vector4f min_pt, max_pt;
00074 getMinMax (sac_model_->getInputCloud (), sac_model_->getIndices (), min_pt, max_pt);
00075 max_pt -= min_pt;
00076 double v = sqrt (max_pt.dot (max_pt));
00077
00078 int n_inliers_count = 0;
00079 size_t indices_size;
00080 unsigned skipped_count = 0;
00081
00082 const unsigned max_skip = max_iterations_ * 10;
00083
00084
00085 while (iterations_ < k && skipped_count < max_skip)
00086 {
00087
00088 sac_model_->getSamples (iterations_, selection);
00089
00090 if (selection.empty ()) break;
00091
00092
00093 if (!sac_model_->computeModelCoefficients (selection, model_coefficients))
00094 {
00095
00096 ++ skipped_count;
00097 continue;
00098 }
00099
00100
00101 sac_model_->getDistancesToModel (model_coefficients, distances);
00102
00103 if (distances.empty ())
00104 {
00105
00106 ++skipped_count;
00107 continue;
00108 }
00109
00110
00111
00112 double gamma = 0.5;
00113 double p_outlier_prob = 0;
00114
00115 indices_size = sac_model_->getIndices ()->size ();
00116 std::vector<double> p_inlier_prob (indices_size);
00117 for (int j = 0; j < iterations_EM_; ++j)
00118 {
00119
00120 for (size_t i = 0; i < indices_size; ++i)
00121 p_inlier_prob[i] = gamma * exp (- (distances[i] * distances[i] ) / 2 * (sigma_ * sigma_) ) /
00122 (sqrt (2 * M_PI) * sigma_);
00123
00124
00125 p_outlier_prob = (1 - gamma) / v;
00126
00127 gamma = 0;
00128 for (size_t i = 0; i < indices_size; ++i)
00129 gamma += p_inlier_prob [i] / (p_inlier_prob[i] + p_outlier_prob);
00130 gamma /= static_cast<double>(sac_model_->getIndices ()->size ());
00131 }
00132
00133
00134 double d_cur_penalty = 0;
00135 for (size_t i = 0; i < indices_size; ++i)
00136 d_cur_penalty += log (p_inlier_prob[i] + p_outlier_prob);
00137 d_cur_penalty = - d_cur_penalty;
00138
00139
00140 if (d_cur_penalty < d_best_penalty)
00141 {
00142 d_best_penalty = d_cur_penalty;
00143
00144
00145 model_ = selection;
00146 model_coefficients_ = model_coefficients;
00147
00148 n_inliers_count = 0;
00149
00150 for (size_t i = 0; i < distances.size (); ++i)
00151 if (distances[i] <= 2 * sigma_)
00152 n_inliers_count++;
00153
00154
00155 double w = static_cast<double> (n_inliers_count) / static_cast<double> (sac_model_->getIndices ()->size ());
00156 double p_no_outliers = 1 - pow (w, static_cast<double> (selection.size ()));
00157 p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers);
00158 p_no_outliers = (std::min) (1 - std::numeric_limits<double>::epsilon (), p_no_outliers);
00159 k = log (1 - probability_) / log (p_no_outliers);
00160 }
00161
00162 ++iterations_;
00163 if (debug_verbosity_level > 1)
00164 PCL_DEBUG ("[pcl::MaximumLikelihoodSampleConsensus::computeModel] Trial %d out of %d. Best penalty is %f.\n", iterations_, static_cast<int> (ceil (k)), d_best_penalty);
00165 if (iterations_ > max_iterations_)
00166 {
00167 if (debug_verbosity_level > 0)
00168 PCL_DEBUG ("[pcl::MaximumLikelihoodSampleConsensus::computeModel] MLESAC reached the maximum number of trials.\n");
00169 break;
00170 }
00171 }
00172
00173 if (model_.empty ())
00174 {
00175 if (debug_verbosity_level > 0)
00176 PCL_DEBUG ("[pcl::MaximumLikelihoodSampleConsensus::computeModel] Unable to find a solution!\n");
00177 return (false);
00178 }
00179
00180
00181 sac_model_->getDistancesToModel (model_coefficients_, distances);
00182 std::vector<int> &indices = *sac_model_->getIndices ();
00183 if (distances.size () != indices.size ())
00184 {
00185 PCL_ERROR ("[pcl::MaximumLikelihoodSampleConsensus::computeModel] Estimated distances (%zu) differs than the normal of indices (%zu).\n", distances.size (), indices.size ());
00186 return (false);
00187 }
00188
00189 inliers_.resize (distances.size ());
00190
00191 n_inliers_count = 0;
00192 for (size_t i = 0; i < distances.size (); ++i)
00193 if (distances[i] <= 2 * sigma_)
00194 inliers_[n_inliers_count++] = indices[i];
00195
00196
00197 inliers_.resize (n_inliers_count);
00198
00199 if (debug_verbosity_level > 0)
00200 PCL_DEBUG ("[pcl::MaximumLikelihoodSampleConsensus::computeModel] Model: %zu size, %d inliers.\n", model_.size (), n_inliers_count);
00201
00202 return (true);
00203 }
00204
00206 template <typename PointT> double
00207 pcl::MaximumLikelihoodSampleConsensus<PointT>::computeMedianAbsoluteDeviation (
00208 const PointCloudConstPtr &cloud,
00209 const boost::shared_ptr <std::vector<int> > &indices,
00210 double sigma)
00211 {
00212 std::vector<double> distances (indices->size ());
00213
00214 Eigen::Vector4f median;
00215
00216 computeMedian (cloud, indices, median);
00217
00218 for (size_t i = 0; i < indices->size (); ++i)
00219 {
00220 pcl::Vector4fMapConst pt = cloud->points[(*indices)[i]].getVector4fMap ();
00221 Eigen::Vector4f ptdiff = pt - median;
00222 ptdiff[3] = 0;
00223 distances[i] = ptdiff.dot (ptdiff);
00224 }
00225
00226 std::sort (distances.begin (), distances.end ());
00227
00228 double result;
00229 size_t mid = indices->size () / 2;
00230
00231 if (indices->size () % 2 == 0)
00232 result = (sqrt (distances[mid-1]) + sqrt (distances[mid])) / 2;
00233 else
00234 result = sqrt (distances[mid]);
00235 return (sigma * result);
00236 }
00237
00239 template <typename PointT> void
00240 pcl::MaximumLikelihoodSampleConsensus<PointT>::getMinMax (
00241 const PointCloudConstPtr &cloud,
00242 const boost::shared_ptr <std::vector<int> > &indices,
00243 Eigen::Vector4f &min_p,
00244 Eigen::Vector4f &max_p)
00245 {
00246 min_p.setConstant (FLT_MAX);
00247 max_p.setConstant (-FLT_MAX);
00248 min_p[3] = max_p[3] = 0;
00249
00250 for (size_t i = 0; i < indices->size (); ++i)
00251 {
00252 if (cloud->points[(*indices)[i]].x < min_p[0]) min_p[0] = cloud->points[(*indices)[i]].x;
00253 if (cloud->points[(*indices)[i]].y < min_p[1]) min_p[1] = cloud->points[(*indices)[i]].y;
00254 if (cloud->points[(*indices)[i]].z < min_p[2]) min_p[2] = cloud->points[(*indices)[i]].z;
00255
00256 if (cloud->points[(*indices)[i]].x > max_p[0]) max_p[0] = cloud->points[(*indices)[i]].x;
00257 if (cloud->points[(*indices)[i]].y > max_p[1]) max_p[1] = cloud->points[(*indices)[i]].y;
00258 if (cloud->points[(*indices)[i]].z > max_p[2]) max_p[2] = cloud->points[(*indices)[i]].z;
00259 }
00260 }
00261
00263 template <typename PointT> void
00264 pcl::MaximumLikelihoodSampleConsensus<PointT>::computeMedian (
00265 const PointCloudConstPtr &cloud,
00266 const boost::shared_ptr <std::vector<int> > &indices,
00267 Eigen::Vector4f &median)
00268 {
00269
00270 std::vector<float> x (indices->size ());
00271 std::vector<float> y (indices->size ());
00272 std::vector<float> z (indices->size ());
00273 for (size_t i = 0; i < indices->size (); ++i)
00274 {
00275 x[i] = cloud->points[(*indices)[i]].x;
00276 y[i] = cloud->points[(*indices)[i]].y;
00277 z[i] = cloud->points[(*indices)[i]].z;
00278 }
00279 std::sort (x.begin (), x.end ());
00280 std::sort (y.begin (), y.end ());
00281 std::sort (z.begin (), z.end ());
00282
00283 size_t mid = indices->size () / 2;
00284 if (indices->size () % 2 == 0)
00285 {
00286 median[0] = (x[mid-1] + x[mid]) / 2;
00287 median[1] = (y[mid-1] + y[mid]) / 2;
00288 median[2] = (z[mid-1] + z[mid]) / 2;
00289 }
00290 else
00291 {
00292 median[0] = x[mid];
00293 median[1] = y[mid];
00294 median[2] = z[mid];
00295 }
00296 median[3] = 0;
00297 }
00298
00299 #define PCL_INSTANTIATE_MaximumLikelihoodSampleConsensus(T) template class PCL_EXPORTS pcl::MaximumLikelihoodSampleConsensus<T>;
00300
00301 #endif // PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_
00302