• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

xd009642 / ndarray-vision / #60

pending completion
#60

push

web-flow
transform update for generic transforms (#60)

Co-authored-by: Todd Keeler <tdk@meta.com>

58 of 58 new or added lines in 2 files covered. (100.0%)

763 of 1111 relevant lines covered (68.68%)

1.42 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.04
/src/transform/affine.rs
1
use super::Transform;
2
use ndarray::{array, prelude::*};
3
use ndarray_linalg::Inverse;
4

5
/// converts a matrix into an equivalent `AffineTransform`
6
pub fn transform_from_2dmatrix(in_array: Array2<f64>) -> AffineTransform {
1✔
7
    let transform = match in_array.inv() {
2✔
8
        Ok(inv) => AffineTransform {
9
            matrix2d_transform: in_array.clone(),
1✔
10
            matrix2d_transform_inverse: inv,
11
            inverse_exists: true,
12
        },
13
        Err(e) => AffineTransform {
14
            matrix2d_transform: in_array.clone(),
×
15
            matrix2d_transform_inverse: Array2::zeros((2, 2)),
×
16
            inverse_exists: false,
17
        },
18
    };
19
    return transform;
1✔
20
}
21

22
/// a linear transform of an image represented by either size 2x2
23
/// or 3x3 ( right column is a translation and projection ) matrix applied to the image index
24
/// coordinates
25
pub struct AffineTransform {
26
    matrix2d_transform: Array2<f64>,
27
    matrix2d_transform_inverse: Array2<f64>,
28
    inverse_exists: bool,
29
}
30

31
fn source_coordinate(p: (f64, f64), trans: ArrayView2<f64>) -> (f64, f64) {
1✔
32
    let p = match trans.shape()[0] {
1✔
33
        2 => array![[p.0], [p.1]],
×
34
        3 => array![[p.0], [p.1], [1.0]],
2✔
35
        _ => unreachable!(),
36
    };
37

38
    let result = trans.dot(&p);
1✔
39
    let x = result[[0, 0]];
2✔
40
    let y = result[[1, 0]];
1✔
41
    let w = match trans.shape()[0] {
1✔
42
        2 => 1.0,
×
43
        3 => result[[2, 0]],
2✔
44
        _ => unreachable!(),
45
    };
46
    if (w - 1.0).abs() > std::f64::EPSILON {
3✔
47
        (x / w, y / w)
×
48
    } else {
49
        (x, y)
1✔
50
    }
51
}
52

53
impl Transform for AffineTransform {
54
    fn apply(&self, p: (f64, f64)) -> (f64, f64) {
×
55
        return source_coordinate(p, self.matrix2d_transform.view());
×
56
    }
57

58
    fn apply_inverse(&self, p: (f64, f64)) -> (f64, f64) {
1✔
59
        return source_coordinate(p, self.matrix2d_transform_inverse.view());
1✔
60
    }
61

62
    fn inverse_exists(&self) -> bool {
×
63
        return self.inverse_exists;
×
64
    }
65
}
66

67
/// describes the Axes to use in rotation_3d
68
/// X and Y correspond to the image index coordinates and
69
/// Z is perpendicular out of the image plane
70
pub enum Axes {
71
    X,
72
    Y,
73
    Z,
74
}
75

76
/// generates a 2d matrix describing a rotation around a 2d coordinate
77
pub fn rotate_around_centre(radians: f64, centre: (f64, f64)) -> Array2<f64> {
1✔
78
    translation(centre.0, centre.1)
3✔
79
        .dot(&rotation_3d(radians, Axes::Z))
1✔
80
        .dot(&translation(-centre.0, -centre.1))
1✔
81
}
82

83
/// generates a matrix describing 2d rotation around origin
84
pub fn rotation_2d(radians: f64) -> Array2<f64> {
×
85
    let s = radians.sin();
×
86
    let c = radians.cos();
×
87
    array![[c, -s], [s, c]]
×
88
}
89

90
/// generates a 3x3 matrix describing a rotation around either the index coordinate axes
91
/// (X,Y) or in the perpendicular axes to the image (Z)
92
pub fn rotation_3d(radians: f64, ax: Axes) -> Array2<f64> {
1✔
93
    let s = radians.sin();
1✔
94
    let c = radians.cos();
1✔
95

96
    match ax {
1✔
97
        Axes::X => array![[1.0, 0.0, 0.0], [0.0, c, -s], [0.0, s, c]],
×
98
        Axes::Y => array![[c, 0.0, s], [0.0, 1.0, 0.0], [-s, 0.0, c]],
×
99
        Axes::Z => array![[c, -s, 0.0], [s, c, 0.0], [0.0, 0.0, 1.0]],
2✔
100
    }
101
}
102

103
/// generates a matrix describing translation in the image index space
104
pub fn translation(x: f64, y: f64) -> Array2<f64> {
1✔
105
    array![[1.0, 0.0, x], [0.0, 1.0, y], [0.0, 0.0, 1.0]]
1✔
106
}
107

108
/// generates a matrix describing scaling in image index space
109
pub fn scale(x: f64, y: f64) -> Array2<f64> {
1✔
110
    array![[x, 0.0, 0.0], [0.0, y, 0.0], [0.0, 0.0, 1.0]]
1✔
111
}
112

113
/// generates a matrix describing shear in image index space
114
pub fn shear(x: f64, y: f64) -> Array2<f64> {
×
115
    array![[1.0, x, 0.0], [y, 1.0, 0.0], [0.0, 0.0, 1.0]]
×
116
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc