mod config;
mod driver;
pub mod estimators;
pub mod kernels;
pub mod magsac;
mod result;
pub mod samples;
pub use config::{ConsensusKind, RansacConfig};
pub use driver::{run, run_parallel};
pub use kernels::{
CauchyKernel, HuberKernel, IdentityKernel, RobustKernel, RobustKernelKind, TukeyKernel,
};
pub use magsac::MagsacConsensus;
pub use result::RansacResult;
pub use samples::{Match2d2d, Match2d3d};
use rand::Rng;
pub trait Estimator {
type Model;
type Sample;
const SAMPLE_SIZE: usize;
fn fit(&self, samples: &[Self::Sample], out: &mut Vec<Self::Model>);
fn residual(&self, model: &Self::Model, sample: &Self::Sample) -> f64;
fn refit(&self, inliers: &[Self::Sample], out: &mut Vec<Self::Model>) {
if inliers.len() < Self::SAMPLE_SIZE {
return;
}
self.fit(&inliers[..Self::SAMPLE_SIZE], out);
}
fn residual_batch(&self, model: &Self::Model, samples: &[Self::Sample], out: &mut [f64]) {
debug_assert_eq!(out.len(), samples.len());
for (i, s) in samples.iter().enumerate() {
out[i] = self.residual(model, s);
}
}
}
pub trait Consensus {
fn consensus(&self, residuals: &[f64], inliers_out: &mut Vec<bool>) -> ConsensusOutcome;
}
#[derive(Debug, Clone, Copy)]
pub struct ConsensusOutcome {
pub score: f64,
pub inlier_count: usize,
}
pub trait Sampler {
fn sample(&mut self, n: usize, out: &mut [usize]);
}
#[derive(Debug, Clone, Copy)]
pub struct ThresholdConsensus {
pub threshold: f64,
}
impl Consensus for ThresholdConsensus {
fn consensus(&self, residuals: &[f64], inliers_out: &mut Vec<bool>) -> ConsensusOutcome {
inliers_out.clear();
inliers_out.reserve(residuals.len());
let mut count = 0usize;
for &r in residuals {
let is_in = r < self.threshold;
inliers_out.push(is_in);
count += is_in as usize;
}
ConsensusOutcome {
score: count as f64,
inlier_count: count,
}
}
}
pub struct UniformSampler<R: Rng> {
rng: R,
}
impl<R: Rng> UniformSampler<R> {
pub fn new(rng: R) -> Self {
Self { rng }
}
}
impl<R: Rng> Sampler for UniformSampler<R> {
fn sample(&mut self, n: usize, out: &mut [usize]) {
let k = out.len();
debug_assert!(k <= n, "sample size {k} exceeds population {n}");
let drawn = rand::seq::index::sample(&mut self.rng, n, k);
for (slot, idx) in out.iter_mut().zip(drawn.iter()) {
*slot = idx;
}
}
}