use ndarray::Array2;
#[cfg(feature = "use_opencv")]
use crate::core_types::RasterType;
#[cfg(feature = "use_opencv")]
use opencv::boxed_ref::{BoxedRef, BoxedRefMut};
#[cfg(feature = "use_opencv")]
use opencv::core;
#[cfg(feature = "use_opencv")]
use opencv::imgproc;
#[cfg(feature = "use_opencv")]
use opencv::prelude::{MatTraitConst, MatTraitConstManual, MatTraitManual};
#[cfg(feature = "use_opencv")]
use opencv::Result;
pub trait Filters<T> {
fn erode(&self, size: usize, kernel_size: i32) -> Array2<T>;
fn dilate(&self, size: usize, kernel_size: i32) -> Array2<T>;
fn median_blur(&self, size: usize) -> Array2<T>;
fn gaussian(&self, kernel_size: usize, sigma: f64) -> Array2<T>;
}
pub type RasterBlockSlice2<T> = Array2<T>;
#[cfg(feature = "use_opencv")]
fn mat_borrow<'a, T>(
rows: i32,
cols: i32,
data: &'a [T],
) -> Result<BoxedRef<'a, core::Mat>>
where
T: opencv::prelude::DataType + 'static,
{
core::Mat::new_rows_cols_with_data::<T>(rows, cols, data)
}
#[cfg(feature = "use_opencv")]
fn mat_borrow_mut<'a, T>(
rows: i32,
cols: i32,
data: &'a mut [T],
) -> Result<BoxedRefMut<'a, core::Mat>>
where
T: opencv::prelude::DataType + 'static,
{
core::Mat::new_rows_cols_with_data_mut::<T>(rows, cols, data)
}
#[cfg(feature = "use_opencv")]
#[deprecated(
since = "0.3.2",
note = "This function copies data. The Filters trait now uses zero-copy internally."
)]
pub fn arrayview2_to_mat<T>(data: ndarray::ArrayView2<'_, T>) -> Result<BoxedRef<'_, core::Mat>>
where
T: opencv::prelude::DataType + 'static,
{
let rows = data.dim().0 as i32;
let cols = data.dim().1 as i32;
let mut mat = unsafe {
core::Mat::new_rows_cols(
rows,
cols,
T::opencv_type(),
)?
};
mat.data_typed_mut::<T>()?
.copy_from_slice(data.as_slice().unwrap());
Ok(mat.into())
}
#[cfg(feature = "use_opencv")]
#[deprecated(
since = "0.3.2",
note = "This function copies data. The Filters trait now uses zero-copy internally."
)]
pub fn mat_to_array2<T>(mat: &core::Mat) -> Result<Array2<T>>
where
T: opencv::prelude::DataType + Clone,
{
let rows = mat.rows() as usize;
let cols = mat.cols() as usize;
let mat_slice: &[T] = mat.data_typed()?;
let array = ndarray::ArrayView2::from_shape((rows, cols), mat_slice)
.unwrap()
.to_owned();
Ok(array)
}
#[cfg(feature = "use_opencv")]
impl<T> Filters<T> for RasterBlockSlice2<T>
where
T: RasterType + opencv::prelude::DataType,
{
fn erode(&self, size: usize, kernel_structure: i32) -> Array2<T> {
let (rows, cols) = self.dim();
let mut output = Array2::<T>::zeros((rows, cols));
let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
let kernel = imgproc::get_structuring_element(
kernel_structure,
core::Size::new(size as i32, size as i32),
core::Point::new(-1, -1),
)
.unwrap();
imgproc::erode(
&src,
&mut dst,
&kernel,
core::Point::new(-1, -1),
1,
core::BORDER_REFLECT,
core::Scalar::all(0.0),
)
.unwrap();
output
}
fn dilate(&self, size: usize, kernel_structure: i32) -> Array2<T> {
let (rows, cols) = self.dim();
let mut output = Array2::<T>::zeros((rows, cols));
let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
let kernel = imgproc::get_structuring_element(
kernel_structure,
core::Size::new(size as i32, size as i32),
core::Point::new(-1, -1),
)
.unwrap();
imgproc::dilate(
&src,
&mut dst,
&kernel,
core::Point::new(-1, -1),
1,
core::BORDER_REFLECT,
core::Scalar::all(0.0),
)
.unwrap();
output
}
fn median_blur(&self, size: usize) -> Array2<T> {
let (rows, cols) = self.dim();
let mut output = Array2::<T>::zeros((rows, cols));
let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
imgproc::median_blur(&src, &mut dst, size.try_into().unwrap()).unwrap();
output
}
fn gaussian(&self, kernel_size: usize, sigma: f64) -> Array2<T> {
let (rows, cols) = self.dim();
let mut output = Array2::<T>::zeros((rows, cols));
let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
let ksize = core::Size::new(kernel_size as i32, kernel_size as i32);
let border_type = core::BORDER_DEFAULT;
let hint = core::AlgorithmHint::ALGO_HINT_DEFAULT;
imgproc::gaussian_blur(&src, &mut dst, ksize, sigma, sigma, border_type, hint).unwrap();
output
}
}