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