65 int iters_so_far,
int max_iters) {
66 if (confidence <= 0.0 || inlier_ratio <= 0.0) {
69 double p = confidence;
70 double w = inlier_ratio;
71 auto m =
static_cast<double>(min_samples);
72 double denom = std::log(std::max(1e-12, 1.0 - std::pow(w, m)));
76 const int niter =
static_cast<int>(std::ceil(std::log(1.0 - p) / denom));
77 return std::clamp(niter, iters_so_far, max_iters);
81inline void find_inliers(
const std::vector<typename Estimator::Datum>& data,
const Model& model,
82 double threshold, std::vector<int>& inliers,
83 std::vector<double>& inlier_residuals) {
85 inlier_residuals.clear();
86 inliers.reserve(data.size());
87 inlier_residuals.reserve(data.size());
88 for (
int i = 0; i < static_cast<int>(data.size()); ++i) {
89 double r = Estimator::residual(model, data[i]);
92 inlier_residuals.push_back(r);
98inline auto refit_model(
const std::vector<typename Estimator::Datum>& data,
const Model& model,
99 const std::vector<int>& inliers,
double threshold,
100 std::vector<int>& updated_inliers, std::vector<double>& updated_residuals)
102 Model refined_model = model;
104 if (
auto m2 = Estimator::refit(data, std::span<const int>(inliers))) {
106 find_inliers<Estimator>(data, refined_model, threshold, updated_inliers,
110 return refined_model;
123 -> RansacResult<typename Estimator::Model> {
124 using Model =
typename Estimator::Model;
126 RansacResult<Model> best;
127 if (data.size() < Estimator::k_min_samples) {
131 std::vector<int> all_indices(data.size());
132 std::vector<int> idxs(Estimator::k_min_samples);
133 std::iota(all_indices.begin(), all_indices.end(), 0);
135 std::mt19937_64 rng(opts.seed);
137 int dynamic_max_iters = opts.max_iters;
138 std::vector<int> inliers;
139 std::vector<double> inlier_residuals;
140 std::vector<int> refined_inliers;
141 std::vector<double> refined_residuals;
143 for (
int it = 0; it < dynamic_max_iters; ++it) {
144 std::sample(all_indices.begin(), all_indices.end(), idxs.begin(), Estimator::k_min_samples,
147 if constexpr (detail::HasDegeneracyCheck<Estimator>) {
148 if (Estimator::is_degenerate(data, std::span<const int>(idxs))) {
153 auto model_opt = Estimator::fit(data, std::span<const int>(idxs));
157 const Model& model = *model_opt;
159 detail::find_inliers<Estimator>(data, model, opts.thresh, inliers, inlier_residuals);
161 if (
static_cast<int>(inliers.size()) < opts.min_inliers) {
165 Model model_refit = model;
166 if (opts.refit_on_inliers) {
167 refined_inliers = inliers;
168 refined_residuals = inlier_residuals;
169 model_refit = detail::refit_model<Estimator>(data, model, inliers, opts.thresh,
170 refined_inliers, refined_residuals);
173 const auto& final_inliers = opts.refit_on_inliers ? refined_inliers : inliers;
174 const auto& final_residuals = opts.refit_on_inliers ? refined_residuals : inlier_residuals;
178 best.inliers.size(), best.inlier_rms)) {
180 best.model = model_refit;
181 best.inliers = final_inliers;
182 best.inlier_rms = final_rms;
186 const double inlier_ratio =
187 static_cast<double>(final_inliers.size()) /
static_cast<double>(data.size());
189 static_cast<int>(Estimator::k_min_samples),
190 it + 1, opts.max_iters);
auto refit_model(const std::vector< typename Estimator::Datum > &data, const Model &model, const std::vector< int > &inliers, double threshold, std::vector< int > &updated_inliers, std::vector< double > &updated_residuals) -> Model