38 #ifndef PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_
39 #define PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_
44 template <
typename Po
intT>
bool
48 if (threshold_ == std::numeric_limits<double>::max())
50 PCL_ERROR (
"[pcl::MaximumLikelihoodSampleConsensus::computeModel] No threshold set!\n");
55 double d_best_penalty = std::numeric_limits<double>::max();
58 std::vector<int> best_model;
59 std::vector<int> selection;
60 Eigen::VectorXf model_coefficients;
61 std::vector<double> distances;
64 sigma_ = computeMedianAbsoluteDeviation (sac_model_->getInputCloud (), sac_model_->getIndices (), threshold_);
65 if (debug_verbosity_level > 1)
66 PCL_DEBUG (
"[pcl::MaximumLikelihoodSampleConsensus::computeModel] Estimated sigma value: %f.\n", sigma_);
69 Eigen::Vector4f min_pt, max_pt;
70 getMinMax (sac_model_->getInputCloud (), sac_model_->getIndices (), min_pt, max_pt);
72 double v =
sqrt (max_pt.dot (max_pt));
74 int n_inliers_count = 0;
76 unsigned skipped_count = 0;
78 const unsigned max_skip = max_iterations_ * 10;
81 while (iterations_ < k && skipped_count < max_skip)
84 sac_model_->getSamples (iterations_, selection);
86 if (selection.empty ())
break;
89 if (!sac_model_->computeModelCoefficients (selection, model_coefficients))
97 sac_model_->getDistancesToModel (model_coefficients, distances);
102 double p_outlier_prob = 0;
104 indices_size = sac_model_->getIndices ()->size ();
105 std::vector<double> p_inlier_prob (indices_size);
106 for (
int j = 0; j < iterations_EM_; ++j)
109 for (
size_t i = 0; i < indices_size; ++i)
110 p_inlier_prob[i] = gamma * exp (- (distances[i] * distances[i] ) / 2 * (sigma_ * sigma_) ) /
111 (
sqrt (2 * M_PI) * sigma_);
114 p_outlier_prob = (1 - gamma) / v;
117 for (
size_t i = 0; i < indices_size; ++i)
118 gamma += p_inlier_prob [i] / (p_inlier_prob[i] + p_outlier_prob);
119 gamma /=
static_cast<double>(sac_model_->getIndices ()->size ());
123 double d_cur_penalty = 0;
124 for (
size_t i = 0; i < indices_size; ++i)
125 d_cur_penalty += log (p_inlier_prob[i] + p_outlier_prob);
126 d_cur_penalty = - d_cur_penalty;
129 if (d_cur_penalty < d_best_penalty)
131 d_best_penalty = d_cur_penalty;
135 model_coefficients_ = model_coefficients;
139 for (
size_t i = 0; i < distances.size (); ++i)
140 if (distances[i] <= 2 * sigma_)
144 double w =
static_cast<double> (n_inliers_count) / static_cast<double> (sac_model_->getIndices ()->size ());
145 double p_no_outliers = 1 - pow (w, static_cast<double> (selection.size ()));
146 p_no_outliers = (std::max) (std::numeric_limits<double>::epsilon (), p_no_outliers);
147 p_no_outliers = (std::min) (1 - std::numeric_limits<double>::epsilon (), p_no_outliers);
148 k = log (1 - probability_) / log (p_no_outliers);
152 if (debug_verbosity_level > 1)
153 PCL_DEBUG (
"[pcl::MaximumLikelihoodSampleConsensus::computeModel] Trial %d out of %d. Best penalty is %f.\n", iterations_, static_cast<int> (ceil (k)), d_best_penalty);
154 if (iterations_ > max_iterations_)
156 if (debug_verbosity_level > 0)
157 PCL_DEBUG (
"[pcl::MaximumLikelihoodSampleConsensus::computeModel] MLESAC reached the maximum number of trials.\n");
164 if (debug_verbosity_level > 0)
165 PCL_DEBUG (
"[pcl::MaximumLikelihoodSampleConsensus::computeModel] Unable to find a solution!\n");
170 sac_model_->getDistancesToModel (model_coefficients_, distances);
171 std::vector<int> &indices = *sac_model_->getIndices ();
172 if (distances.size () != indices.size ())
174 PCL_ERROR (
"[pcl::MaximumLikelihoodSampleConsensus::computeModel] Estimated distances (%zu) differs than the normal of indices (%zu).\n", distances.size (), indices.size ());
178 inliers_.resize (distances.size ());
181 for (
size_t i = 0; i < distances.size (); ++i)
182 if (distances[i] <= 2 * sigma_)
183 inliers_[n_inliers_count++] = indices[i];
186 inliers_.resize (n_inliers_count);
188 if (debug_verbosity_level > 0)
189 PCL_DEBUG (
"[pcl::MaximumLikelihoodSampleConsensus::computeModel] Model: %zu size, %d inliers.\n", model_.size (), n_inliers_count);
195 template <
typename Po
intT>
double
198 const boost::shared_ptr <std::vector<int> > &indices,
201 std::vector<double> distances (indices->size ());
203 Eigen::Vector4f median;
207 for (
size_t i = 0; i < indices->size (); ++i)
210 Eigen::Vector4f ptdiff = pt - median;
212 distances[i] = ptdiff.dot (ptdiff);
215 std::sort (distances.begin (), distances.end ());
218 size_t mid = indices->size () / 2;
220 if (indices->size () % 2 == 0)
221 result = (
sqrt (distances[mid-1]) +
sqrt (distances[mid])) / 2;
223 result =
sqrt (distances[mid]);
224 return (sigma * result);
228 template <
typename Po
intT>
void
231 const boost::shared_ptr <std::vector<int> > &indices,
232 Eigen::Vector4f &min_p,
233 Eigen::Vector4f &max_p)
235 min_p.setConstant (FLT_MAX);
236 max_p.setConstant (-FLT_MAX);
237 min_p[3] = max_p[3] = 0;
239 for (
size_t i = 0; i < indices->size (); ++i)
241 if (cloud->points[(*indices)[i]].x < min_p[0]) min_p[0] = cloud->points[(*indices)[i]].x;
242 if (cloud->points[(*indices)[i]].y < min_p[1]) min_p[1] = cloud->points[(*indices)[i]].y;
243 if (cloud->points[(*indices)[i]].z < min_p[2]) min_p[2] = cloud->points[(*indices)[i]].z;
245 if (cloud->points[(*indices)[i]].x > max_p[0]) max_p[0] = cloud->points[(*indices)[i]].x;
246 if (cloud->points[(*indices)[i]].y > max_p[1]) max_p[1] = cloud->points[(*indices)[i]].y;
247 if (cloud->points[(*indices)[i]].z > max_p[2]) max_p[2] = cloud->points[(*indices)[i]].z;
252 template <
typename Po
intT>
void
255 const boost::shared_ptr <std::vector<int> > &indices,
256 Eigen::Vector4f &median)
259 std::vector<float> x (indices->size ());
260 std::vector<float> y (indices->size ());
261 std::vector<float> z (indices->size ());
262 for (
size_t i = 0; i < indices->size (); ++i)
264 x[i] = cloud->points[(*indices)[i]].x;
265 y[i] = cloud->points[(*indices)[i]].y;
266 z[i] = cloud->points[(*indices)[i]].z;
268 std::sort (x.begin (), x.end ());
269 std::sort (y.begin (), y.end ());
270 std::sort (z.begin (), z.end ());
272 size_t mid = indices->size () / 2;
273 if (indices->size () % 2 == 0)
275 median[0] = (x[mid-1] + x[mid]) / 2;
276 median[1] = (y[mid-1] + y[mid]) / 2;
277 median[2] = (z[mid-1] + z[mid]) / 2;
288 #define PCL_INSTANTIATE_MaximumLikelihoodSampleConsensus(T) template class PCL_EXPORTS pcl::MaximumLikelihoodSampleConsensus<T>;
290 #endif // PCL_SAMPLE_CONSENSUS_IMPL_MLESAC_H_