use alloc::vec;
use alloc::vec::Vec;
use crate::matrix::Matrix;
use crate::traits::FloatScalar;
use super::ImageError;
pub fn gaussian_kernel_1d<T: FloatScalar>(sigma: T, truncate: T) -> Result<Vec<T>, ImageError> {
if !sigma.is_finite() || sigma <= T::zero() {
return Err(ImageError::InvalidParameter);
}
if !truncate.is_finite() || truncate <= T::zero() {
return Err(ImageError::InvalidParameter);
}
let radius_f = (truncate * sigma).ceil();
let radius: usize = radius_f.to_usize().ok_or(ImageError::InvalidParameter)?;
let len = 2 * radius + 1;
let two = T::one() + T::one();
let inv_two_sigma_sq = T::one() / (two * sigma * sigma);
let mut kernel = Vec::with_capacity(len);
let mut sum = T::zero();
for i in 0..len {
let x = T::from(i as isize - radius as isize).unwrap();
let v = (-(x * x) * inv_two_sigma_sq).exp();
kernel.push(v);
sum = sum + v;
}
let inv_sum = T::one() / sum;
for v in kernel.iter_mut() {
*v = *v * inv_sum;
}
Ok(kernel)
}
pub fn box_kernel_1d<T: FloatScalar>(n: usize) -> Result<Vec<T>, ImageError> {
if n == 0 || n % 2 == 0 {
return Err(ImageError::InvalidKernelSize);
}
let v = T::one() / T::from(n).unwrap();
Ok(vec![v; n])
}
pub fn sobel_x_3x3<T: FloatScalar>() -> Matrix<T, 3, 3> {
let m1 = -T::one();
let z = T::zero();
let p1 = T::one();
let m2 = m1 + m1;
let p2 = p1 + p1;
Matrix::new([[m1, z, p1], [m2, z, p2], [m1, z, p1]])
}
pub fn sobel_y_3x3<T: FloatScalar>() -> Matrix<T, 3, 3> {
let m1 = -T::one();
let z = T::zero();
let p1 = T::one();
let m2 = m1 + m1;
let p2 = p1 + p1;
Matrix::new([[m1, m2, m1], [z, z, z], [p1, p2, p1]])
}
pub fn scharr_x_3x3<T: FloatScalar>() -> Matrix<T, 3, 3> {
let three = T::from(3.0_f64).unwrap();
let ten = T::from(10.0_f64).unwrap();
let z = T::zero();
Matrix::new([[-three, z, three], [-ten, z, ten], [-three, z, three]])
}
pub fn scharr_y_3x3<T: FloatScalar>() -> Matrix<T, 3, 3> {
let three = T::from(3.0_f64).unwrap();
let ten = T::from(10.0_f64).unwrap();
let z = T::zero();
Matrix::new([[-three, -ten, -three], [z, z, z], [three, ten, three]])
}
pub fn laplacian_3x3<T: FloatScalar>() -> Matrix<T, 3, 3> {
let z = T::zero();
let one = T::one();
let m4 = -(one + one + one + one);
Matrix::new([[z, one, z], [one, m4, one], [z, one, z]])
}
pub fn laplacian_3x3_diag<T: FloatScalar>() -> Matrix<T, 3, 3> {
let one = T::one();
let two = one + one;
let four = two + two;
let m8 = -(four + four);
Matrix::new([[one, one, one], [one, m8, one], [one, one, one]])
}