Implement gradient thresholding for Canny filter

This commit is contained in:
cdo committed 2026-10-27 19:09:05 +00:00
1 parent 6258219ff2
commit ba0c3b4756
1 file changed
+79
+79
View File
@@ -0,0 +1,79 @@
use super::*;
use crate::*;
#[derive(Clone, Copy, PartialEq)]
struct Step {
x: isize,
y: isize,
}
impl Step {
fn of(mut theta: f32) -> Self {
theta /= std::f32::consts::PI;
if theta < 0.0 {
theta += 1.0;
}
if theta <= 0.125 {
Self { x: 1, y: 0 }
} else if theta <= 0.375 {
Self { x: 1, y: 1 }
} else if theta <= 0.625 {
Self { x: 0, y: 1 }
} else if theta <= 0.875 {
Self { x: -1, y: 1 }
} else if theta <= 1.0 {
Self { x: 1, y: 0 }
} else {
panic!("Angle out of expected range");
}
}
fn back(&self) -> Self {
Self {
x: -self.x,
y: -self.y,
}
}
fn from(&self, x: usize, y: usize) -> (isize, isize) {
(x as isize + self.x, y as isize + self.y)
}
}
impl Default for Step {
fn default() -> Self {
Step { x: 0, y: 0 }
}
}
pub fn gradient_threshold(img: Image<filter::sobel::Vector>) -> Image<f32> {
let mut result = image::Image::<f32>::with_extent(img.extent);
result.for_each(|x, y, p| {
let value = img.at(x, y);
let step = Step::of(value.direction);
let this = value.magnitude;
let next = get(&img, step.from(x, y))
.map_or(f32::NEG_INFINITY, |v| v.magnitude);
let prev = get(&img, step.back().from(x, y))
.map_or(f32::NEG_INFINITY, |v| v.magnitude);
if this > next && this > prev {
*p = this;
}
});
result
}
fn get<T: Copy>(img: &Image<T>, pos: (isize, isize)) -> Option<T> {
if pos.0 >= 0
&& pos.0 < img.extent.x as isize
&& pos.1 >= 0
&& pos.1 < img.extent.y as isize
{
Some(img.at(pos.0 as usize, pos.1 as usize))
} else {
None
}
}