pub mod absolute_pose;
pub mod essential;
pub mod fundamental;
pub mod homography;
pub mod line;
pub mod rigid_transform;
pub use absolute_pose::AbsolutePoseEstimator;
pub use essential::EssentialEstimator;
pub use fundamental::FundamentalEstimator;
pub use homography::HomographyEstimator;
pub use line::LineEstimator;
pub use rigid_transform::RigidTransformEstimator;
#[cfg(test)]
mod tests {
use super::{FundamentalEstimator, HomographyEstimator, RigidTransformEstimator};
use crate::core::Estimator;
use crate::types::DataMatrix;
#[test]
fn homography_estimator_recovers_simple_translation() {
let tx = 1.0;
let ty = 2.0;
let correspondences = [(0.0, 0.0), (1.0, 0.0), (0.0, 1.0), (1.0, 1.0)];
let mut data = DataMatrix::zeros(4, 4);
for (i, (x, y)) in correspondences.iter().enumerate() {
data[(i, 0)] = *x;
data[(i, 1)] = *y;
data[(i, 2)] = x + tx;
data[(i, 3)] = y + ty;
}
let estimator = HomographyEstimator::new();
let sample = [0usize, 1, 2, 3];
assert!(estimator.is_valid_sample(&data, &sample));
let models = estimator.estimate_model(&data, &sample);
assert_eq!(models.len(), 1);
let homography = &models[0];
assert!(
estimator.is_valid_model(homography, &data, &sample, 0.0),
"Estimated homography should satisfy basic determinant constraints"
);
}
#[test]
fn fundamental_estimator_produces_valid_model() {
let mut data = DataMatrix::zeros(8, 4);
let points = [
(0.0, 0.0, 10.0, 10.0),
(10.0, 0.0, 20.0, 10.0),
(0.0, 10.0, 10.0, 20.0),
(10.0, 10.0, 20.0, 20.0),
(5.0, 5.0, 15.0, 15.0),
(15.0, 5.0, 25.0, 15.0),
(5.0, 15.0, 15.0, 25.0),
(15.0, 15.0, 25.0, 25.0),
];
for (i, (x1, y1, x2, y2)) in points.iter().enumerate() {
data[(i, 0)] = *x1;
data[(i, 1)] = *y1;
data[(i, 2)] = *x2;
data[(i, 3)] = *y2;
}
let estimator = FundamentalEstimator::new();
let sample: Vec<usize> = (0..8).collect();
assert!(estimator.is_valid_sample(&data, &sample));
let models = estimator.estimate_model(&data, &sample);
assert!(!models.is_empty(), "Should produce at least one model");
if let Some(fundamental) = models.first() {
let det = fundamental.f.determinant().abs();
assert!(
det < 1.0,
"Fundamental matrix should have small determinant: {}",
det
);
}
}
#[test]
fn rigid_transform_estimator_produces_valid_model() {
let mut data = DataMatrix::zeros(3, 6);
data[(0, 0)] = 0.0;
data[(0, 1)] = 0.0;
data[(0, 2)] = 0.0;
data[(0, 3)] = 1.0;
data[(0, 4)] = 0.0;
data[(0, 5)] = 0.0;
data[(1, 0)] = 1.0;
data[(1, 1)] = 0.0;
data[(1, 2)] = 0.0;
data[(1, 3)] = 1.0;
data[(1, 4)] = 1.0;
data[(1, 5)] = 0.0;
data[(2, 0)] = 0.0;
data[(2, 1)] = 1.0;
data[(2, 2)] = 0.0;
data[(2, 3)] = 0.0;
data[(2, 4)] = 1.0;
data[(2, 5)] = 0.0;
let estimator = RigidTransformEstimator::new();
let sample = [0usize, 1, 2];
assert!(estimator.is_valid_sample(&data, &sample));
let models = estimator.estimate_model(&data, &sample);
assert!(!models.is_empty(), "Should produce at least one model");
if let Some(transform) = models.first() {
assert!(
estimator.is_valid_model(transform, &data, &sample, 1.0),
"Estimated rigid transform should be valid"
);
let r = transform.rotation.to_rotation_matrix();
let det = r.matrix().determinant();
assert!(
(det - 1.0).abs() < 0.1,
"Rotation should have determinant close to 1"
);
}
}
}