Use proptest for kernel convolution

This commit is contained in:
cdo committed 2026-10-26 15:52:20 +00:00
1 parent 96d1af5b78
commit a3743dd921
1 file changed
+40 -30
+40 -30
View File
@@ -32,10 +32,7 @@ impl<const N: usize> Kernel for [[f32; N]; N] {
result.for_each(|x, y, p| { result.for_each(|x, y, p| {
for i in 0..N { for i in 0..N {
for j in 0..N { for j in 0..N {
let img_x = x as usize + i; *p += img.at(x + i, y + j) * self[j][i];
let img_y = y as usize + j;
let idx = img_y * img.extent.x as usize + img_x;
*p += img.pixels[idx] * self[j][i];
} }
} }
*p /= mag; *p /= mag;
@@ -47,6 +44,7 @@ impl<const N: usize> Kernel for [[f32; N]; N] {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use proptest::prelude::*;
#[test] #[test]
fn size_of_result_img() { fn size_of_result_img() {
@@ -60,37 +58,49 @@ mod tests {
assert_eq!(output.extent.y, 8); assert_eq!(output.extent.y, 8);
} }
proptest! {
#[test] #[test]
fn single_pixel_result() { fn single_pixel_result_3x3(
p1 in 0.1f32..1.0,
p2 in 0.0f32..1.0,
p3 in 0.0f32..1.0,
p4 in 0.0f32..1.0,
p5 in 0.0f32..1.0,
p6 in 0.0f32..1.0,
p7 in 0.0f32..1.0,
p8 in 0.0f32..1.0,
p9 in 0.0f32..1.0,
k1 in 0.0f32..1.0,
k2 in 0.0f32..1.0,
k3 in 0.0f32..1.0,
k4 in 0.0f32..1.0,
k5 in 0.0f32..1.0,
k6 in 0.0f32..1.0,
k7 in 0.0f32..1.0,
k8 in 0.0f32..1.0,
k9 in 0.0f32..1.0,
) {
let input = image::Image { let input = image::Image {
extent: image::Extent { x: 3, y: 3 }, extent: image::Extent { x: 5, y: 5 },
pixels: vec![ pixels: vec![
image::SRGB::new(0.1, 0.0, 0.0), 10.0, 10.0, 10.0, 10.0, 10.0,
image::SRGB::new(0.0, 0.2, 0.0), 10.0, p1, p2, p3, 10.0,
image::SRGB::new(0.0, 0.0, 0.3), 10.0, p4, p5, p6, 10.0,
image::SRGB::new(0.2, 0.0, 0.0), 10.0, p7, p8, p9, 10.0,
image::SRGB::new(0.0, 0.3, 0.0), 10.0, 10.0, 10.0, 10.0, 10.0,
image::SRGB::new(0.0, 0.0, 0.1),
image::SRGB::new(0.3, 0.0, 0.0),
image::SRGB::new(0.0, 0.1, 0.0),
image::SRGB::new(0.0, 0.0, 0.2),
], ],
}; };
let kernel = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6], [0.7, 0.8, 0.9]]; let kernel = [[k1, k2, k3], [k4, k5, k6], [k7, k8, k9]];
let output = kernel.convolve(&input); let output = kernel.convolve(&input);
assert_eq!(output.extent.x, 1); prop_assert_eq!(output.extent.x, 3);
assert_eq!(output.extent.y, 1); prop_assert_eq!(output.extent.y, 3);
assert_eq!(
output.pixels[0].r, let mag = k1 + k2 + k3 + k4 + k5 + k6 + k7 + k8 + k9;
(0.1 * 0.1 + 0.2 * 0.4 + 0.3 * 0.7) / 4.5, let sum = p1 * k1 + p2 * k2 + p3 * k3
); + p4 * k4 + p5 * k5 + p6 * k6
assert_eq!( + p7 * k7 + p8 * k8 + p9 * k9;
output.pixels[0].g, let exp = sum / mag;
(0.2 * 0.2 + 0.3 * 0.5 + 0.1 * 0.8) / 4.5, prop_assert!((output.at(1, 1) - exp).abs() < 1e-6);
); }
assert_eq!(
output.pixels[0].b,
(0.3 * 0.3 + 0.1 * 0.6 + 0.2 * 0.9) / 4.5,
);
} }
} }