use kornia_3d::camera::PinholeCamera;
use kornia_3d::pose::Pose3d;
use kornia_image::ImageSize;
use kornia_imgproc::features::OrbFeatures;
#[derive(Debug, Clone)]
pub struct Frame {
pub idx: usize,
pub features: OrbFeatures,
pub pose_world_to_cam: Pose3d,
pub image_size: ImageSize,
pub keypoint_colors: Vec<[u8; 3]>,
pub u_right: Vec<f32>,
pub depth: Vec<f32>,
pub keypoints_undist: Vec<[f32; 2]>,
}
impl Frame {
pub fn is_stereo(&self) -> bool {
!self.depth.is_empty()
}
pub fn ensure_undistorted(&mut self, camera: &PinholeCamera) {
if self.keypoints_undist.len() == self.features.keypoints_xy.len() {
return;
}
self.keypoints_undist = self
.features
.keypoints_xy
.iter()
.map(|kp| {
let p = camera.undistort(kp[0] as f64, kp[1] as f64);
[p.x as f32, p.y as f32]
})
.collect();
}
pub fn undistorted_xy(&self, i: usize, camera: &PinholeCamera) -> Option<[f32; 2]> {
if !self.keypoints_undist.is_empty() {
return self.keypoints_undist.get(i).copied();
}
self.features.keypoints_xy.get(i).map(|kp| {
let p = camera.undistort(kp[0] as f64, kp[1] as f64);
[p.x as f32, p.y as f32]
})
}
pub fn stereo_depth(&self, i: usize) -> Option<f32> {
match self.depth.get(i) {
Some(&z) if z > 0.0 => Some(z),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use kornia_imgproc::features::OrbFeatures;
fn empty_frame(u_right: Vec<f32>, depth: Vec<f32>) -> Frame {
Frame {
idx: 0,
features: OrbFeatures {
keypoints_xy: Vec::new(),
orientations: Vec::new(),
descriptors: Vec::new(),
octaves: Vec::new(),
},
pose_world_to_cam: Pose3d::IDENTITY,
image_size: ImageSize {
width: 1,
height: 1,
},
keypoint_colors: Vec::new(),
u_right,
depth,
keypoints_undist: Vec::new(),
}
}
#[test]
fn monocular_frame_reports_no_stereo() {
let frame = empty_frame(Vec::new(), Vec::new());
assert!(!frame.is_stereo());
assert_eq!(frame.stereo_depth(0), None);
}
#[test]
fn stereo_frame_reports_valid_depth() {
let frame = empty_frame(vec![10.0, -1.0], vec![2.5, -1.0]);
assert!(frame.is_stereo());
assert_eq!(frame.stereo_depth(0), Some(2.5));
assert_eq!(frame.stereo_depth(1), None); assert_eq!(frame.stereo_depth(2), None); }
}