use anyd::detect::{LocateOptions, locate};
fn main() {
let path = std::env::args().nth(1).expect("usage: locdebug <png>");
let rgba = oxideav_png::decode_png_to_rgba(&std::fs::read(&path).unwrap()).unwrap();
let (w, h) = (rgba.width as usize, rgba.height as usize);
let luma: Vec<u8> = rgba
.data
.chunks_exact(4)
.map(|p| ((p[0] as u32 * 299 + p[1] as u32 * 587 + p[2] as u32 * 114) / 1000) as u8)
.collect();
let frame = anyd::GrayFrame::new(&luma, w, h).unwrap();
let env = |k: &str| std::env::var(k).ok().and_then(|v| v.parse().ok());
let mut opts = LocateOptions::default();
if let Some(v) = env("LOC_MAX") {
opts.max_candidates = v as usize;
}
if let Some(v) = env("LOC_FRAC") {
opts.max_region_frac = v;
}
if let Some(v) = env("LOC_DENSITY") {
opts.edge_density = v;
}
if let Some(v) = env("LOC_DOWNSCALE") {
opts.downscale = v as usize;
}
let cands = locate(&frame, &opts);
let thr = anyd::imgproc::threshold::otsu_threshold(&frame);
println!("frame {w}x{h}: {} candidates (otsu {thr})", cands.len());
for c in &cands {
let cr = c.location.outline.corners;
let (xs, ys): (Vec<f32>, Vec<f32>) = (
cr.iter().map(|p| p.x).collect(),
cr.iter().map(|p| p.y).collect(),
);
let (x0, y0) = (
xs.iter().cloned().fold(f32::MAX, f32::min),
ys.iter().cloned().fold(f32::MAX, f32::min),
);
let (x1, y1) = (
xs.iter().cloned().fold(0.0, f32::max),
ys.iter().cloned().fold(0.0, f32::max),
);
let fam = c
.symbology
.map(|s| format!("{:?}", s.dimension()))
.unwrap_or("?".into());
let (bx0, by0) = (x0.max(0.0) as usize, y0.max(0.0) as usize);
let (bx1, by1) = ((x1 as usize).min(w), (y1 as usize).min(h));
let mut dark = 0u64;
for yy in by0..by1 {
for xx in bx0..bx1 {
if luma[yy * w + xx] <= thr {
dark += 1;
}
}
}
let area = ((bx1 - bx0) * (by1 - by0)).max(1) as f64;
println!(
" {fam:8} ({:.0},{:.0})-({:.0},{:.0}) {:.0}x{:.0} dark {:.2}",
x0,
y0,
x1,
y1,
x1 - x0,
y1 - y0,
dark as f64 / area
);
}
}