#[inline]
pub fn nms_and_threshold_slice(
mag: &[f32],
dir: &[u8],
edge_out: &mut [u8],
width: usize,
x_start: usize,
x_end: usize,
y: usize,
low_thresh: f32,
high_thresh: f32,
) {
debug_assert!(x_start >= 1, "x_start must be >= 1");
debug_assert!(x_end <= width - 1, "x_end must be <= width - 1");
debug_assert!(y >= 1, "y must be >= 1");
debug_assert_eq!(mag.len(), dir.len());
debug_assert_eq!(mag.len(), edge_out.len());
#[cfg(debug_assertions)]
log::trace!(
"[nms] y={}, x=[{}, {}), low={:.2}, high={:.2}",
y,
x_start,
x_end,
low_thresh,
high_thresh
);
let w = width as isize;
let offsets: [[isize; 2]; 4] = [
[-1, 1], [-w + 1, w - 1], [-w, w], [-w - 1, w + 1], ];
let base_idx = y * width;
for x in x_start..x_end {
let idx = base_idx + x;
let m = mag[idx];
if m < low_thresh {
edge_out[idx] = 0;
continue;
}
let d = dir[idx] as usize;
#[cfg(debug_assertions)]
if d > 3 {
log::error!(
"[nms] CORRUPTED dir={} at idx={} (x={}, y={}), skipping",
d,
idx,
x,
y
);
edge_out[idx] = 0;
continue;
}
let off1 = offsets[d][0];
let off2 = offsets[d][1];
let n1_idx = (idx as isize + off1) as usize;
let n2_idx = (idx as isize + off2) as usize;
let m1 = mag[n1_idx];
let m2 = mag[n2_idx];
if m >= m1 && m > m2 {
edge_out[idx] = if m >= high_thresh { 255 } else { 127 };
} else {
edge_out[idx] = 0;
}
}
#[cfg(debug_assertions)]
log::trace!("[nms] DONE y={}, x=[{}, {})", y, x_start, x_end);
}
#[cfg(debug_assertions)]
pub fn nms_and_threshold_with_stats(
mag: &[f32],
dir: &[u8],
edge_out: &mut [u8],
width: usize,
x_start: usize,
x_end: usize,
y: usize,
low_thresh: f32,
high_thresh: f32,
) -> (usize, usize, usize) {
use std::time::Instant;
let t_start = Instant::now();
nms_and_threshold_slice(
mag,
dir,
edge_out,
width,
x_start,
x_end,
y,
low_thresh,
high_thresh,
);
let base_idx = y * width;
let mut strong = 0usize;
let mut weak = 0usize;
let mut supp = 0usize;
for x in x_start..x_end {
match edge_out[base_idx + x] {
255 => strong += 1,
127 => weak += 1,
_ => supp += 1,
}
}
let total = x_end - x_start;
log::debug!(
"[nms_stats] y={} strong={} ({:.1}%) weak={} ({:.1}%) supp={} ({:.1}%) {:.3}ms",
y,
strong,
strong as f64 / total as f64 * 100.0,
weak,
weak as f64 / total as f64 * 100.0,
supp,
supp as f64 / total as f64 * 100.0,
t_start.elapsed().as_secs_f64() * 1000.0
);
(strong, weak, supp)
}