image_convolution/
kernels.rs1use crate::Real;
2
3pub struct Kernel {
5 pub data: Vec<Real>, pub size: u32,
7}
8
9impl std::ops::Index<(u32, u32)> for Kernel {
10 type Output = Real;
11
12 #[inline]
13 fn index(&self, (x, y): (u32, u32)) -> &Self::Output {
14 let idx = (y * self.size + x) as usize;
15 &self.data[idx]
16 }
17}
18
19pub fn gaussian(sigma: Real) -> Kernel {
21 let prec = 3.0;
30 let radius = (sigma * (2.0 * prec * (10.0 as Real).ln()).sqrt()).ceil() as i32;
31 let size = 1 + 2 * radius; let mut data = Vec::with_capacity((size * size) as usize);
33 for y in -radius..=radius {
34 for x in -radius..=radius {
35 let dist2 = x.pow(2) + y.pow(2);
36 let value = if dist2 <= radius * radius {
38 (-0.5 * (dist2 as Real) / sigma.powi(2)).exp()
39 } else {
40 0.0
41 };
42 data.push(value);
43 }
44 }
45
46 let sum: Real = data.iter().sum();
48 if sum > 0.0 {
49 for v in data.iter_mut() {
50 *v /= sum;
51 }
52 }
53
54 Kernel {
55 data,
56 size: size as u32,
57 }
58}
59
60pub fn roberts_operator() -> (Kernel, Kernel) {
61 let kx = Kernel {
62 data: vec![1.0, 0.0, 0.0, -1.0],
63 size: 2,
64 };
65 let ky = Kernel {
66 data: vec![0.0, 1.0, -1.0, 0.0],
67 size: 2,
68 };
69 (kx, ky)
70}
71
72pub fn desolneux_operator() -> (Kernel, Kernel) {
73 let kx = Kernel {
74 data: vec![-0.5, 0.5, -0.5, 0.5],
75 size: 2,
76 };
77 let ky = Kernel {
78 data: vec![-0.5, -0.5, 0.5, 0.5],
79 size: 2,
80 };
81 (kx, ky)
82}
83
84pub fn sobel_operator() -> (Kernel, Kernel) {
85 let kx = Kernel {
86 data: vec![-1.0, 0.0, 1.0, -2.0, 0.0, 2.0, -1.0, 0.0, 1.0],
87 size: 3,
88 };
89 let ky = Kernel {
90 data: vec![-1.0, -2.0, -1.0, 0.0, 0.0, 0.0, 1.0, 2.0, 1.0],
91 size: 3,
92 };
93 (kx, ky)
94}
95
96pub fn freichen_operator() -> (Kernel, Kernel) {
97 let sqrt_2 = (2.0 as Real).sqrt();
98 let kx = Kernel {
99 data: vec![-1.0, 0.0, 1.0, -sqrt_2, 0.0, sqrt_2, -1.0, 0.0, 1.0],
100 size: 3,
101 };
102 let ky = Kernel {
103 data: vec![-1.0, -sqrt_2, -1.0, 0.0, 0.0, 0.0, 1.0, sqrt_2, 1.0],
104 size: 3,
105 };
106 (kx, ky)
107}