Implement gradient thresholding for Canny filter
This commit is contained in:
1 parent
6258219ff2
commit
ba0c3b4756
1 file changed
+79
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user