Implement automatic double threshold for Canny filter
This commit is contained in:
1 parent
ba0c3b4756
commit
7e62163c26
1 file changed
+85
@@ -0,0 +1,85 @@
|
|||||||
|
use crate::image::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
pub enum Candidate {
|
||||||
|
None,
|
||||||
|
Weak,
|
||||||
|
Strong,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Candidate {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn double_threshold(img: Image<f32>) -> Image<Candidate> {
|
||||||
|
let t = otsu::<20>(&img.pixels);
|
||||||
|
let mut result = Image::<Candidate>::with_extent(img.extent);
|
||||||
|
result.for_each(|x, y, p| {
|
||||||
|
let value = img.at(x, y);
|
||||||
|
*p = if value < t / 2.0 {
|
||||||
|
Candidate::None
|
||||||
|
} else if value < t {
|
||||||
|
Candidate::Weak
|
||||||
|
} else {
|
||||||
|
Candidate::Strong
|
||||||
|
}
|
||||||
|
});
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn otsu<const N: usize>(values: &Vec<f32>) -> f32 {
|
||||||
|
let mut hist = [0.0; N];
|
||||||
|
for x in values {
|
||||||
|
let bin = std::cmp::min(N - 1, (*x * (N as f32)) as usize);
|
||||||
|
hist[bin] += 1.0;
|
||||||
|
}
|
||||||
|
for i in 0..N {
|
||||||
|
hist[i] /= values.len() as f32;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut max = 0.0;
|
||||||
|
let mut res = 0;
|
||||||
|
for t in 0..N {
|
||||||
|
let var = variance(t, hist);
|
||||||
|
if var > max {
|
||||||
|
res = t;
|
||||||
|
max = var;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res as f32 / N as f32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn variance<const N: usize>(t: usize, hist: [f32; N]) -> f32 {
|
||||||
|
let omega_0 = omega(0, t, hist);
|
||||||
|
let omega_1 = omega(t, N, hist);
|
||||||
|
|
||||||
|
let mu_0 = mu(0, t, hist, omega_0);
|
||||||
|
let mu_1 = mu(t, N, hist, omega_1);
|
||||||
|
|
||||||
|
omega_0 * omega_1 * (mu_0 - mu_1).powf(2.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn omega<const N: usize>(from: usize, to: usize, hist: [f32; N]) -> f32 {
|
||||||
|
let mut sum = 0.0;
|
||||||
|
for i in from..to {
|
||||||
|
sum += hist[i];
|
||||||
|
}
|
||||||
|
sum
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mu<const N: usize>(
|
||||||
|
from: usize,
|
||||||
|
to: usize,
|
||||||
|
hist: [f32; N],
|
||||||
|
omega: f32,
|
||||||
|
) -> f32 {
|
||||||
|
let mut sum = 0.0;
|
||||||
|
for i in from..to {
|
||||||
|
let bin_centre = (i as f32 + 0.5) / N as f32;
|
||||||
|
sum += bin_centre * hist[i];
|
||||||
|
}
|
||||||
|
sum / omega
|
||||||
|
}
|
||||||
Reference in new issue
Block a user