in opensfm/src/robust/robust_estimator.h [38:117]
ScoreInfo<typename MODEL::Type> Estimate(
const std::vector<typename MODEL::Data>& samples, const SCORING& scorer,
const RobustEstimatorParams& params) {
// For now, we use this default one, we could be extended to PROSAC sampling
RandomSamplesGenerator<std::mt19937> random_generator;
ScoreInfo<typename MODEL::Type> best_score;
bool should_stop = false;
for (int i = 0; i < params.iterations && !should_stop; ++i) {
// Generate and compute some models
const auto random_samples = random_generator.GetRandomSamples<MODEL>(
samples, MODEL::MINIMAL_SAMPLES);
typename MODEL::Type models[MODEL::MAX_MODELS];
const auto models_count = MODEL::Estimate(random_samples.begin(),
random_samples.end(), &models[0]);
// Compute model's errors for each generated model
for (int j = 0; j < models_count && !should_stop; ++j) {
auto errors =
MODEL::EvaluateModel(models[j], samples.begin(), samples.end());
// Compute score based on errors
ScoreInfo<typename MODEL::Type> score =
scorer.Score(errors.begin(), errors.end(), best_score);
score.model = models[j];
score.lo_model = models[j];
// Keep the best score (bigger, the better)
best_score = std::max(score, best_score);
const bool best_found =
score.score == best_score.score &&
score.inliers_indices.size() >= MODEL::MINIMAL_SAMPLES;
// Run local optimization (inner non-minimal RANSAC on inliers)
if (best_found && params.use_local_optimization) {
for (int k = 0; k < params.local_optimization_iterations; ++k) {
// Gather inliers and use them for getting random sample
std::vector<typename MODEL::Data> inliers_samples;
for (const auto idx : best_score.inliers_indices) {
inliers_samples.push_back(samples[idx]);
}
// Same as Matas papers : min(inliers/2, 12)
const int lo_sample_size_clamp = 12;
const int lo_sample_size =
std::max(std::min(lo_sample_size_clamp,
int(best_score.inliers_indices.size() * 0.5)),
MODEL::MINIMAL_SAMPLES);
const auto lo_random_samples =
random_generator.GetRandomSamples<MODEL>(inliers_samples,
lo_sample_size);
typename MODEL::Type lo_models[MODEL::MAX_MODELS];
const auto lo_models_count =
MODEL::EstimateNonMinimal(lo_random_samples.begin(),
lo_random_samples.end(), &lo_models[0]);
for (int l = 0; l < lo_models_count; ++l) {
// Compute LO model's errors on all samples
auto lo_errors = MODEL::EvaluateModel(lo_models[l], samples.begin(),
samples.end());
// Compute LO score based on errors
ScoreInfo<typename MODEL::Type> lo_score =
scorer.Score(lo_errors.begin(), lo_errors.end(), best_score);
lo_score.model = best_score.model;
lo_score.lo_model = lo_models[l];
// Keep the best score (bigger, the better)
best_score = std::max(lo_score, best_score);
}
}
}
// Based on actual inliers ratio, we might stop here
should_stop = ShouldStop<MODEL>(params, best_score, samples.size(), i);
}
}
return best_score;
}