Skip to content

Commit

Permalink
implement box_blur_fast ops with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
light-le committed Jan 16, 2025
1 parent 2c5c101 commit 9108613
Showing 1 changed file with 106 additions and 2 deletions.
108 changes: 106 additions & 2 deletions crates/kornia-imgproc/src/filter/ops.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use kornia_image::{Image, ImageError};
use kornia_image::{Image, ImageError, ImageSize};

use super::{kernels, separable_filter};
use super::{kernels, separable_filter, fast_horizontal_filter};

/// Blur an image using a box blur filter
///
Expand Down Expand Up @@ -79,3 +79,107 @@ pub fn sobel<const C: usize>(

Ok(())
}



/// Blur an image using a box blur filter multiple times to achieve a near gaussian blur
///
/// # Arguments
///
/// * `src` - The source image with shape (H, W, C).
/// * `dst` - The destination image with shape (H, W, C).
/// * `kernel_size` - The size of the kernel (kernel_x, kernel_y).
/// * `sigma` - The sigma of the gaussian kernel.
///
/// PRECONDITION: `src` and `dst` must have the same shape.
pub fn box_blur_fast<const C: usize>(
src: &Image<f32, C>,
dst: &mut Image<f32, C>,
sigma: (f32, f32),
) -> Result<(), ImageError> {
let half_kernel_x_sizes = kernels::box_blur_fast_kernels_1d(sigma.0, 3);
let half_kernel_y_sizes = kernels::box_blur_fast_kernels_1d(sigma.1, 3);

let transposed_size = ImageSize {
width: src.size().height,
height: src.size().width,
};

let mut input_img = src.clone();
for (half_kernel_x_size, half_kernel_y_size) in half_kernel_x_sizes.iter().zip(half_kernel_y_sizes.iter()) {
let mut transposed = Image::<f32, C>::from_size_val(transposed_size, 0.0)?;

fast_horizontal_filter(&input_img, &mut transposed, *half_kernel_x_size)?;
fast_horizontal_filter(&transposed, dst, *half_kernel_y_size)?;

input_img = dst.clone();
}

Ok(())
}


#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_box_blur_fast() -> Result<(), ImageError> {
let size = ImageSize {
width: 5,
height: 5,
};

#[rustfmt::skip]
let img = Image::new(
size,
(0..25).map(|x| x as f32).collect(),
)?;
let mut dst = Image::<_, 1>::from_size_val(size, 0.0)?;

box_blur_fast(&img, &mut dst, (0.5, 0.5))?;

assert_eq!(
dst.as_slice(),
&[
4.444444, 4.9259257, 5.7037034, 6.4814816, 6.962963,
6.851851, 7.3333335, 8.111111, 8.888889, 9.370372,
10.740741, 11.222222, 12.0, 12.777779, 13.259262,
14.629628, 15.111112, 15.888888, 16.666666, 17.14815,
17.037035, 17.518518, 18.296295, 19.074074, 19.555555,
],
);

Ok(())
}

#[test]
fn test_gaussian_blur() -> Result<(), ImageError> {
let size = ImageSize {
width: 5,
height: 5,
};

#[rustfmt::skip]
let img = Image::new(
size,
(0..25).map(|x| x as f32).collect(),
)?;

let mut dst = Image::<_, 1>::from_size_val(size, 0.0)?;

gaussian_blur(&img, &mut dst, (3, 3), (0.5, 0.5))?;

assert_eq!(
dst.as_slice(),
&[
0.57097936, 1.4260278, 2.3195207, 3.213014, 3.5739717,
4.5739717, 5.999999, 7.0, 7.999999, 7.9349294,
9.041435, 10.999999, 12.0, 12.999998, 12.402394,
13.5089, 15.999998, 17.0, 17.999996, 16.86986,
15.58594, 18.230816, 19.124311, 20.017801, 18.588936,
]
);
Ok(())
}
}

0 comments on commit 9108613

Please sign in to comment.