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