use crate::generic_model::{CameraModel, ModelCast};
use nalgebra as na;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Clone, Copy, Default, Debug)]
pub struct Ftheta<T: na::RealField + Clone> {
pub fx: T,
pub fy: T,
pub cx: T,
pub cy: T,
pub k2: T,
pub k3: T,
pub k4: T,
pub k5: T,
pub k6: T,
pub width: u32,
pub height: u32,
}
impl<T: na::RealField + Clone> ModelCast<T> for Ftheta<T> {}
impl<T: na::RealField + Clone> Ftheta<T> {
pub fn new(params: &na::DVector<T>, width: u32, height: u32) -> Ftheta<T> {
Ftheta {
fx: params[0].clone(),
fy: params[1].clone(),
cx: params[2].clone(),
cy: params[3].clone(),
k2: params[4].clone(),
k3: params[5].clone(),
k4: params[6].clone(),
k5: params[7].clone(),
k6: params[8].clone(),
width,
height,
}
}
pub fn zeros() -> Ftheta<T> {
Ftheta {
fx: T::zero(),
fy: T::zero(),
cx: T::zero(),
cy: T::zero(),
k2: T::zero(),
k3: T::zero(),
k4: T::zero(),
k5: T::zero(),
k6: T::zero(),
width: 0,
height: 0,
}
}
fn f_theta(k2: &T, k3: &T, k4: &T, k5: &T, k6: &T, theta: &T) -> T {
let theta2 = theta.clone() * theta.clone();
let theta3 = theta2.clone() * theta.clone();
let theta4 = theta3.clone() * theta.clone();
let theta5 = theta4.clone() * theta.clone();
let theta6 = theta5.clone() * theta.clone();
theta.clone()
+ k2.clone() * theta2
+ k3.clone() * theta3
+ k4.clone() * theta4
+ k5.clone() * theta5
+ k6.clone() * theta6
}
pub fn from<U: na::RealField + Clone>(m: &Ftheta<U>) -> Ftheta<T> {
Ftheta::new(&m.cast(), m.width, m.height)
}
}
impl<T: na::RealField + Clone> CameraModel<T> for Ftheta<T> {
fn set_params(&mut self, params: &nalgebra::DVector<T>) {
if params.shape() != self.params().shape() {
panic!("params has wrong shape.")
}
self.fx = params[0].clone();
self.fy = params[1].clone();
self.cx = params[2].clone();
self.cy = params[3].clone();
self.k2 = params[4].clone();
self.k3 = params[5].clone();
self.k4 = params[6].clone();
self.k5 = params[7].clone();
self.k6 = params[8].clone();
}
fn params(&self) -> nalgebra::DVector<T> {
na::dvector![
self.fx.clone(),
self.fy.clone(),
self.cx.clone(),
self.cy.clone(),
self.k2.clone(),
self.k3.clone(),
self.k4.clone(),
self.k5.clone(),
self.k6.clone(),
]
}
fn width(&self) -> T {
T::from_u32(self.width).unwrap()
}
fn height(&self) -> T {
T::from_u32(self.height).unwrap()
}
fn project_one(&self, pt: &nalgebra::Vector3<T>) -> nalgebra::Vector2<T> {
let params = self.params();
let x = pt[0].clone();
let y = pt[1].clone();
let z = pt[2].clone();
let r_xy = (x.clone() * x.clone() + y.clone() * y.clone()).sqrt();
let theta = r_xy.clone().atan2(z);
let fx = ¶ms[0];
let fy = ¶ms[1];
let cx = ¶ms[2];
let cy = ¶ms[3];
let k2 = ¶ms[4];
let k3 = ¶ms[5];
let k4 = ¶ms[6];
let k5 = ¶ms[7];
let k6 = ¶ms[8];
let theta_d = Self::f_theta(k2, k3, k4, k5, k6, &theta);
let (mx, my) = if r_xy > T::from_f64(1e-6).unwrap() {
let d = theta_d / r_xy;
(x * d.clone(), y * d)
} else {
(T::zero(), T::zero())
};
let px = fx.clone() * mx + cx.clone();
let py = fy.clone() * my + cy.clone();
na::Vector2::new(px, py)
}
fn unproject_one(&self, pt: &nalgebra::Vector2<T>) -> nalgebra::Vector3<T> {
let xd = (pt[0].clone() - self.cx.clone()) / self.fx.clone();
let yd = (pt[1].clone() - self.cy.clone()) / self.fy.clone();
let rd2 = xd.clone() * xd.clone() + yd.clone() * yd.clone();
let rd = rd2.sqrt();
let theta_threshold = T::from_f64(1e-6).unwrap();
let one = T::from_f64(1.0).unwrap();
let zero = T::from_f64(0.0).unwrap();
if rd > theta_threshold {
let mut lower = T::zero();
let mut upper = T::pi();
for _ in 0..50 {
let mid = (lower.clone() + upper.clone()) / T::from_f64(2.0).unwrap();
let f_val = Self::f_theta(&self.k2, &self.k3, &self.k4, &self.k5, &self.k6, &mid);
if f_val < rd {
lower = mid;
} else {
upper = mid;
}
}
let theta = (lower + upper) / T::from_f64(2.0).unwrap();
let sin_theta = theta.clone().sin();
let cos_theta = theta.cos();
na::Vector3::new(
xd * sin_theta.clone() / rd.clone(),
yd * sin_theta / rd,
cos_theta,
)
} else {
na::Vector3::new(zero.clone(), zero, one)
}
}
fn camera_params(&self) -> nalgebra::DVector<T> {
na::dvector![
self.fx.clone(),
self.fy.clone(),
self.cx.clone(),
self.cy.clone()
]
}
fn distortion_params(&self) -> nalgebra::DVector<T> {
na::dvector![
self.k2.clone(),
self.k3.clone(),
self.k4.clone(),
self.k5.clone(),
self.k6.clone(),
]
}
fn set_w_h(&mut self, w: u32, h: u32) {
self.width = w;
self.height = h;
}
fn distortion_params_bound(&self) -> Vec<(usize, (f64, f64))> {
vec![
(4, (-1.0, 1.0)),
(5, (-1.0, 1.0)),
(6, (-1.0, 1.0)),
(7, (-1.0, 1.0)),
(8, (-1.0, 1.0)),
]
}
}