use nalgebra::*;
pub histogram(pixels : &[u8]) -> DVector<u8> {
let mut hist : DVector<u8> = DVector::from_element(256, 0);
for px in pixels {
hist[px] += 1;
}
hist
}
pub binary_threshold(pixels : &DMatrix<u8>, thr : u8) -> DMatrix<u8> {
partition_threshold(pixels, thr, 255)
}
pub partition_threshold(
pixels : &DMatrix<u8>,
thr_low : u8,
thr_high : u8
) -> DMatrix<u8> {
let thr_map : DMatrix<u8> = DMatrix::zeros(pixels.nrows(), pixels.ncols());
for (thr, px) in thr_map.iter_mut().zip(pixels.iter()) {
if px >= thr_low && px < thr_high {
*thr = 255
}
}
thr_map
}
pub backproject(pixels : &DMatrix<u8>, tol : u8) -> DMatrix<u8> {
let hist = histogram(pixels.as_slice());
let peak = hist.iamax_full();
let thr_min = (peak - tol).min(0);
let thr_max = (peak + tol).max(255);
partition_threshold(pixels, thr_min, thr_max)
}
pub threshold_indices(pixels : &DMatrix<u8>) -> Vec<(usize, usize)> {
let mut valid_pos = Vec::new();
for (c_ix, col) in pixels.column_iter().enumerate() {
for (r_ix, r_el) in col.iter().enumerate() {
if r_el > 0 {
valid_pos.push((r_ix, c_ix));
}
}
}
valid_pos
}
pub mean_shift(
data : &DMatrix<f32>,
c : f32,
tol : f32,
mut max_iter : usize
) -> Result<DVector<f32>, &'static str> {
let mut curr_est : DVector<f32> = data.row_mean();
while max_iter > 0 {
let mut smooth_est = data.row_iter().zip(curr_est.row_iter())
.map(|data, est| data - est);
smooth_est.row_iter_mut().for_each(|r| r.for_each(e){ *e = (-1.*c*e.powf(2.)).exp(); });
let smooth_w_data_rows : Vec<_> = smooth_est.row_iter()
.zip(data.row_iter())
.map(|smooth, data| smooth.component_mul(data) )
.collect();
let smooth_w_data = DMatrix::from_rows(smooth_w_data_rows);
curr_est.copy_from(&smooth_w_data.sum_columns().component_div(smooth_est.sum_columns()));
if curr_est.norm() < tol {
return Ok(curr_est);
}
}
Err("Maximum number of iterations reached")
}