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