models_cv/
lib.rs

1extern crate nalgebra as na;
2
3pub mod camera_features;
4pub mod filter;
5pub mod io;
6pub mod gltf;
7pub mod obj;
8pub mod rasterizer;
9pub mod triangle;
10
11use std::iter::zip;
12use std::collections::HashMap;
13use ordered_float::OrderedFloat;
14
15use na::{Vector2,Vector3,Matrix3,Matrix4xX,Matrix3x4, Matrix3xX, Point3};
16use triangle::Triangle;
17
18/**
19 * Returns A vector of indexed points in image space where the index represents the column of the corresponding 3D point matrix in camera space
20 */
21pub fn project_points(points: &Vec<Vector3<f32>>, intrinsic_matrix: &Matrix3<f32>, view_matrix: &Matrix3x4<f32>) -> (Vec<(usize,Vector2<f32>)>, Matrix3xX<f32>) {
22    let mut ps = Matrix4xX::<f32>::from_element(points.len(), 1.0);
23    let mut vec_id_map = HashMap::<(OrderedFloat<f32>,OrderedFloat<f32>,OrderedFloat<f32>),usize>::with_capacity(points.len());
24
25    for i in 0..points.len() {
26        let p = &points[i];
27        let key = (OrderedFloat(p.x),OrderedFloat(p.y),OrderedFloat(p.z));
28        if !vec_id_map.contains_key(&key) {
29            vec_id_map.insert(key, i);
30        }   
31        ps.fixed_view_mut::<3,1>(0,i).copy_from(p);
32    }
33    let points_cam = view_matrix*(&ps);
34    let projected_points = intrinsic_matrix*&points_cam;
35
36    let screen_points_with_idx = projected_points.column_iter().enumerate()
37        .map(|(i,c)|{
38            let orig_p = ps.column(i);
39            let key = (OrderedFloat(orig_p.x),OrderedFloat(orig_p.y),OrderedFloat(orig_p.z));
40            (*vec_id_map.get(&key).expect("point not present in key map"),c)
41        } )
42        .filter(|(_,c)| c.z != 0.0)
43        .map(|(i,c)| (i,(c.x/c.z,c.y/c.z)))
44        .map(|(i,(x,y))| (i,Vector2::new(x, y)))
45        .collect::<Vec<_>>();
46    (screen_points_with_idx, points_cam)
47}
48
49pub fn group_points_to_triangles(pixels_with_id: &Vec<(usize,Vector2<f32>)>, cam_points: &Matrix3xX<f32>) -> Vec<(Triangle<2>,Triangle<3>)> {
50    (0..pixels_with_id.len()-2).step_by(3).map(|i| {
51        let (id_0,pix_v0) = pixels_with_id[i];
52        let (id_1,pix_v1) = pixels_with_id[i+1];
53        let (id_2,pix_v2) = pixels_with_id[i+2];
54        let cam_point_v0 = cam_points.column(id_0);
55        let cam_point_v1 = cam_points.column(id_1);
56        let cam_point_v2 = cam_points.column(id_2);
57        (
58            Triangle::from_vec(&pix_v0.cast::<f32>(), Some(id_0) ,&pix_v1.cast::<f32>(), Some(id_1), &pix_v2.cast::<f32>(), Some(id_2)),
59            Triangle::from_view(&cam_point_v0, Some(id_0), &cam_point_v1, Some(id_1), &cam_point_v2, Some(id_2))
60        )
61    }).collect::<Vec<_>>()
62}
63
64pub fn filter_screen_points_for_camera_views(points: &Vec<Vector3<f32>>, intrinsic_matrix: &Matrix3<f32>, view_matrices: &Vec<Matrix3x4<f32>>, screen_width: f32, screen_height: f32, filter_type: filter::FilterType) -> Vec<Vec<(usize,Vector2<usize>)>> {
65    view_matrices.iter().map(|view_matrix| {
66        let (points_screen_with_idx, points_cam) = project_points(points, &intrinsic_matrix, &view_matrix.fixed_view::<3,4>(0, 0).into_owned());
67        match filter_type {
68            filter::FilterType::Depth => filter::filter_visible_screen_points_by_depth(&points_screen_with_idx,&points_cam),
69            filter::FilterType::Rasterizer => {
70                let screen_cam_triangles = group_points_to_triangles(&points_screen_with_idx,&points_cam);
71                filter::filter_visible_screen_points_by_rasterizer(&screen_cam_triangles,screen_width, screen_height)
72            }
73        }
74    }).collect::<Vec<_>>()
75}
76
77
78pub fn generate_matches(view_matrices: &Vec<Matrix3x4<f32>>, intrinsic_matrices: &Vec<Matrix3<f32>>, features: &Vec<Vec<(usize,Vector2<usize>)>>) -> Vec<camera_features::CameraFeatures> {
79    assert_eq!(view_matrices.len(), features.len());
80    zip(zip(view_matrices,intrinsic_matrices),features).enumerate().map(|(cam_id,((view_matrix,intrinsic_matrix),screen_points_with_id))| {
81        let point_map = screen_points_with_id.into_iter().map(|&(k,v)| (k,v)).collect::<HashMap<usize,Vector2<usize>>>();
82        camera_features::CameraFeatures::new(point_map,cam_id,view_matrix.clone(),intrinsic_matrix.clone()) 
83    }).collect()
84}
85
86pub fn generate_camera_trajectory(start: &Point3<f32>, target: &Point3<f32>, arc_angle: f32, step_count: usize) -> Vec<Point3<f32>> {
87    assert!(arc_angle > 0.0 && arc_angle <= 360.0);
88    let pos = start-target;
89    let r = pos.iter().map(|v| v.powi(2)).sum::<f32>().sqrt();
90    let theta = (pos.y/r).acos();
91    let phi = pos.z.atan2(pos.x);
92    let arc_angle_rad = arc_angle * std::f32::consts::PI/180.0;
93
94    (0..step_count+1).map(|s|{
95        let ratio = (s as f32) / (step_count as f32);
96        let rad_offset = ratio*arc_angle_rad;
97        let p = phi + rad_offset;
98        let x_new = target.x + r*theta.sin()*p.cos();
99        let y_new = target.y;
100        let z_new = target.x + r*theta.sin()*p.sin();
101        Point3::<f32>::new(x_new,y_new,z_new)
102    }).collect()
103}
104
105