use crate::*; const THETA_N: usize = 200; #[derive(Clone, Copy, Debug)] pub struct Line { pub theta: f32, pub rho: f32, pub significance: f32, } pub fn transform(img: image::Image) -> image::Image { let diag = ((img.extent.x.pow(2) + img.extent.y.pow(2)) as f32).sqrt(); let mut res = image::Image::::with_extent(image::Extent { x: THETA_N, y: diag as usize, }); for y in 0..img.extent.y { for x in 0..img.extent.x { if img.at(x, y).y != 1.0 { continue; } for a in 0..THETA_N { let theta = theta_from(a); let rho = x as f32 * theta.cos() + y as f32 * theta.sin(); if rho < 0.0 { continue; } *res.at_mut(a, rho as usize) += 1.0; } } } res } pub fn lines( min_significance: f32, img: image::Image, ) -> Vec { let hough = transform(img); let mu = stats::mean((&hough.pixels).into_iter().map(|p| *p)); let sigma = stats::stddev((&hough.pixels).into_iter().map(|p| *p), mu); let mut lines = Vec::::new(); for y in 0..hough.extent.y { for x in 0..hough.extent.x { let value = hough.at(x, y); let significance = (value - mu) / sigma; if significance >= min_significance { let theta = theta_from(x); let rho = y as f32; lines.push(Line { theta, rho, significance, }); } } } lines } fn theta_from(x: usize) -> f32 { x as f32 * std::f32::consts::PI / THETA_N as f32 }