1use ndarray::Array2;
19
20#[cfg(feature = "use_opencv")]
21use crate::core_types::RasterType;
22#[cfg(feature = "use_opencv")]
23use opencv::boxed_ref::{BoxedRef, BoxedRefMut};
24#[cfg(feature = "use_opencv")]
25use opencv::core;
26#[cfg(feature = "use_opencv")]
27use opencv::imgproc;
28#[cfg(feature = "use_opencv")]
29use opencv::prelude::{MatTraitConst, MatTraitConstManual, MatTraitManual};
30#[cfg(feature = "use_opencv")]
31use opencv::Result;
32
33pub trait Filters<T> {
38 fn erode(&self, size: usize, kernel_size: i32) -> Array2<T>;
40 fn dilate(&self, size: usize, kernel_size: i32) -> Array2<T>;
42 fn median_blur(&self, size: usize) -> Array2<T>;
44 fn gaussian(&self, kernel_size: usize, sigma: f64) -> Array2<T>;
46}
47
48pub type RasterBlockSlice2<T> = Array2<T>;
50
51#[cfg(feature = "use_opencv")]
58fn mat_borrow<'a, T>(
59 rows: i32,
60 cols: i32,
61 data: &'a [T],
62) -> Result<BoxedRef<'a, core::Mat>>
63where
64 T: opencv::prelude::DataType + 'static,
65{
66 core::Mat::new_rows_cols_with_data::<T>(rows, cols, data)
67}
68
69#[cfg(feature = "use_opencv")]
74fn mat_borrow_mut<'a, T>(
75 rows: i32,
76 cols: i32,
77 data: &'a mut [T],
78) -> Result<BoxedRefMut<'a, core::Mat>>
79where
80 T: opencv::prelude::DataType + 'static,
81{
82 core::Mat::new_rows_cols_with_data_mut::<T>(rows, cols, data)
83}
84
85#[cfg(feature = "use_opencv")]
92#[deprecated(
93 since = "0.3.2",
94 note = "This function copies data. The Filters trait now uses zero-copy internally."
95)]
96pub fn arrayview2_to_mat<T>(data: ndarray::ArrayView2<'_, T>) -> Result<BoxedRef<'_, core::Mat>>
97where
98 T: opencv::prelude::DataType + 'static,
99{
100 let rows = data.dim().0 as i32;
101 let cols = data.dim().1 as i32;
102
103 let mut mat = unsafe {
104 core::Mat::new_rows_cols(
105 rows,
106 cols,
107 T::opencv_type(),
108 )?
109 };
110
111 mat.data_typed_mut::<T>()?
112 .copy_from_slice(data.as_slice().unwrap());
113
114 Ok(mat.into())
115}
116
117#[cfg(feature = "use_opencv")]
122#[deprecated(
123 since = "0.3.2",
124 note = "This function copies data. The Filters trait now uses zero-copy internally."
125)]
126pub fn mat_to_array2<T>(mat: &core::Mat) -> Result<Array2<T>>
127where
128 T: opencv::prelude::DataType + Clone,
129{
130 let rows = mat.rows() as usize;
131 let cols = mat.cols() as usize;
132
133 let mat_slice: &[T] = mat.data_typed()?;
134
135 let array = ndarray::ArrayView2::from_shape((rows, cols), mat_slice)
136 .unwrap()
137 .to_owned();
138
139 Ok(array)
140}
141
142#[cfg(feature = "use_opencv")]
143impl<T> Filters<T> for RasterBlockSlice2<T>
144where
145 T: RasterType + opencv::prelude::DataType,
146{
147 fn erode(&self, size: usize, kernel_structure: i32) -> Array2<T> {
148 let (rows, cols) = self.dim();
149 let mut output = Array2::<T>::zeros((rows, cols));
150
151 let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
153 let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
154 let kernel = imgproc::get_structuring_element(
155 kernel_structure,
156 core::Size::new(size as i32, size as i32),
157 core::Point::new(-1, -1),
158 )
159 .unwrap();
160
161 imgproc::erode(
162 &src,
163 &mut dst,
164 &kernel,
165 core::Point::new(-1, -1),
166 1,
167 core::BORDER_REFLECT,
168 core::Scalar::all(0.0),
169 )
170 .unwrap();
171
172 output
174 }
175
176 fn dilate(&self, size: usize, kernel_structure: i32) -> Array2<T> {
177 let (rows, cols) = self.dim();
178 let mut output = Array2::<T>::zeros((rows, cols));
179
180 let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
181 let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
182 let kernel = imgproc::get_structuring_element(
183 kernel_structure,
184 core::Size::new(size as i32, size as i32),
185 core::Point::new(-1, -1),
186 )
187 .unwrap();
188
189 imgproc::dilate(
190 &src,
191 &mut dst,
192 &kernel,
193 core::Point::new(-1, -1),
194 1,
195 core::BORDER_REFLECT,
196 core::Scalar::all(0.0),
197 )
198 .unwrap();
199
200 output
201 }
202
203 fn median_blur(&self, size: usize) -> Array2<T> {
204 let (rows, cols) = self.dim();
205 let mut output = Array2::<T>::zeros((rows, cols));
206
207 let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
208 let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
209
210 imgproc::median_blur(&src, &mut dst, size.try_into().unwrap()).unwrap();
211
212 output
213 }
214
215 fn gaussian(&self, kernel_size: usize, sigma: f64) -> Array2<T> {
216 let (rows, cols) = self.dim();
217 let mut output = Array2::<T>::zeros((rows, cols));
218
219 let src = mat_borrow::<T>(rows as i32, cols as i32, self.as_slice().unwrap()).unwrap();
220 let mut dst = mat_borrow_mut::<T>(rows as i32, cols as i32, output.as_slice_mut().unwrap()).unwrap();
221
222 let ksize = core::Size::new(kernel_size as i32, kernel_size as i32);
223 let border_type = core::BORDER_DEFAULT;
224 let hint = core::AlgorithmHint::ALGO_HINT_DEFAULT;
225 imgproc::gaussian_blur(&src, &mut dst, ksize, sigma, sigma, border_type, hint).unwrap();
226
227 output
228 }
229}