scan_core/transform/
perspective.rs1use crate::Point;
2
3pub struct PerspectiveTransform {
6 coeffs: [f32; 9],
7 coeffs_inv: [f32; 9],
8}
9
10impl PerspectiveTransform {
11 pub fn new(src: &[Point], dst: &[Point]) -> Option<Self> {
12 if src.len() != 4 || dst.len() != 4 {
13 return None;
14 }
15
16 let coeffs = get_normalization_coefficients(src, dst, false)?;
17 let coeffs_inv = get_normalization_coefficients(src, dst, true)?;
18
19 Some(Self {
20 coeffs,
21 coeffs_inv,
22 })
23 }
24
25 pub fn transform(&self, x: f32, y: f32) -> Point {
26 let c = self.coeffs;
27 let den = c[6] * x + c[7] * y + 1.0;
28 Point {
29 x: (c[0] * x + c[1] * y + c[2]) / den,
30 y: (c[3] * x + c[4] * y + c[5]) / den,
31 }
32 }
33
34 pub fn transform_inverse(&self, x: f32, y: f32) -> Point {
35 let c = self.coeffs_inv;
36 let den = c[6] * x + c[7] * y + 1.0;
37 Point {
38 x: (c[0] * x + c[1] * y + c[2]) / den,
39 y: (c[3] * x + c[4] * y + c[5]) / den,
40 }
41 }
42
43 }
45
46fn get_normalization_coefficients(src: &[Point], dst: &[Point], is_inverse: bool) -> Option<[f32; 9]> {
47 let (src, dst) = if is_inverse { (dst, src) } else { (src, dst) };
48
49 let mut matrix = [[0.0f32; 9]; 8];
60
61 for i in 0..4 {
67 let s = src[i];
68 let d = dst[i];
69 matrix[2 * i][0] = s.x;
71 matrix[2 * i][1] = s.y;
72 matrix[2 * i][2] = 1.0;
73 matrix[2 * i][6] = -d.x * s.x;
74 matrix[2 * i][7] = -d.x * s.y;
75 matrix[2 * i][8] = d.x;
76
77 matrix[2 * i + 1][3] = s.x;
79 matrix[2 * i + 1][4] = s.y;
80 matrix[2 * i + 1][5] = 1.0;
81 matrix[2 * i + 1][6] = -d.y * s.x;
82 matrix[2 * i + 1][7] = -d.y * s.y;
83 matrix[2 * i + 1][8] = d.y;
84 }
85
86 let n = 8;
88 for i in 0..n {
89 let mut pivot_row = i;
91 for j in i + 1..n {
92 if matrix[j][i].abs() > matrix[pivot_row][i].abs() {
93 pivot_row = j;
94 }
95 }
96
97 matrix.swap(i, pivot_row);
98
99 let pivot = matrix[i][i];
100 if pivot.abs() < 1e-6 {
101 return None; }
103
104 for j in i..=n {
106 matrix[i][j] /= pivot;
107 }
108
109 for k in 0..n {
111 if k != i {
112 let factor = matrix[k][i];
113 for j in i..=n {
114 matrix[k][j] -= factor * matrix[i][j];
115 }
116 }
117 }
118 }
119
120 let mut res = [0.0; 9];
121 for i in 0..8 {
122 res[i] = matrix[i][8];
123 }
124 res[8] = 1.0;
125
126 Some(res)
127}