Add threshold filter
This commit is contained in:
1 parent
cdcab41c73
commit
5b940c2192
4 files changed
+85
-64
No files matched your search
@@ -1,5 +1,8 @@
|
||||
pub mod canny;
|
||||
pub mod sobel;
|
||||
pub mod threshold;
|
||||
|
||||
pub use canny::canny;
|
||||
pub use sobel::sobel;
|
||||
pub use threshold::threshold;
|
||||
pub use threshold::threshold_auto;
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::image::*;
|
||||
use crate::*;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum Candidate {
|
||||
@@ -14,72 +15,16 @@ impl Default for Candidate {
|
||||
}
|
||||
|
||||
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 {
|
||||
let t = filter::threshold::otsu::<20, _>(
|
||||
(&img.pixels).into_iter().map(|p| *p),
|
||||
);
|
||||
img.map(|p| {
|
||||
if p < t / 2.0 {
|
||||
Candidate::None
|
||||
} else if value < t {
|
||||
} else if p < 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
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
use crate::image::*;
|
||||
|
||||
pub fn threshold_auto(img: Image<Luminance>) -> Image<Luminance> {
|
||||
let t = otsu::<20, _>((&img.pixels).into_iter().map(|p| p.y));
|
||||
threshold(t, img)
|
||||
}
|
||||
|
||||
pub fn threshold(t: f32, mut img: Image<Luminance>) -> Image<Luminance> {
|
||||
img.for_each(|_, _, p| {
|
||||
p.y = if p.y >= t { 1.0 } else { 0.0 };
|
||||
});
|
||||
img
|
||||
}
|
||||
|
||||
pub fn otsu<const N: usize, I>(values: I) -> f32
|
||||
where
|
||||
I: Iterator<Item = f32>,
|
||||
{
|
||||
let mut hist = [0.0; N];
|
||||
let mut n = 0;
|
||||
for x in values {
|
||||
let bin = std::cmp::min(N - 1, (x * (N as f32)) as usize);
|
||||
hist[bin] += 1.0;
|
||||
n += 1;
|
||||
}
|
||||
for i in 0..N {
|
||||
hist[i] /= n 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
|
||||
}
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
pub mod filter;
|
||||
pub mod image;
|
||||
pub mod kernel;
|
||||
pub mod filter;
|
||||
Reference in new issue
Block a user