pub mod epnp;
pub mod ransac;
pub mod refine;
mod ops;
pub use epnp::{EPnP, EPnPParams};
use kornia_algebra::{Mat3AF32, Vec2F32, Vec3AF32};
use kornia_imgproc::calibration::distortion::PolynomialDistortion;
pub use ransac::{solve_pnp_ransac, PnPRansacError, PnPRansacResult, RansacParams};
pub use refine::{refine_pose_lm, LMRefineParams};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum PnPError {
#[error("PnP solver requires at least {required} 2D-3D correspondences, got {actual}")]
InsufficientCorrespondences {
required: usize,
actual: usize,
},
#[error("Mismatched array lengths: {left_name} ({left_len}) != {right_name} ({right_len})")]
MismatchedArrayLengths {
left_name: &'static str,
left_len: usize,
right_name: &'static str,
right_len: usize,
},
#[error("SVD computation failed: {0}")]
SvdFailed(String),
}
#[derive(Debug, Clone)]
pub struct NumericTol {
pub svd: f32,
pub eps: f32,
}
impl Default for NumericTol {
fn default() -> Self {
Self {
svd: 1e-12,
eps: 1e-12,
}
}
}
#[derive(Debug, Clone)]
pub struct PnPResult {
pub rotation: Mat3AF32,
pub translation: Vec3AF32,
pub rvec: Vec3AF32,
pub reproj_rmse: Option<f32>,
pub num_iterations: Option<usize>,
pub converged: Option<bool>,
}
pub trait PnPSolver {
type Param;
fn solve(
world: &[Vec3AF32],
image: &[Vec2F32],
k: &Mat3AF32,
distortion: Option<&PolynomialDistortion>,
params: &Self::Param,
) -> Result<PnPResult, PnPError>;
}
#[derive(Debug, Clone)]
pub enum PnPMethod {
EPnP(EPnPParams),
EPnPDefault,
}
pub fn solve_pnp(
world: &[Vec3AF32],
image: &[Vec2F32],
k: &Mat3AF32,
distortion: Option<&PolynomialDistortion>,
method: PnPMethod,
) -> Result<PnPResult, PnPError> {
match method {
PnPMethod::EPnP(params) => EPnP::solve(world, image, k, distortion, ¶ms),
PnPMethod::EPnPDefault => EPnP::solve(world, image, k, distortion, &EPnPParams::default()),
}
}