use nalgebra::Point2;
use projective_grid::{detect_regular_grid, RegularGridError};
fn warped_grid(cols: i32, rows: i32) -> Vec<Point2<f32>> {
#[rustfmt::skip]
let h = [
[42.0_f32, 4.0, 90.0],
[2.5, 40.0, 70.0],
[3.0e-4, 1.5e-4, 1.0 ],
];
let mut points = Vec::new();
for j in 0..rows {
for i in 0..cols {
let (x, y) = (i as f32, j as f32);
let w = h[2][0] * x + h[2][1] * y + h[2][2];
let px = (h[0][0] * x + h[0][1] * y + h[0][2]) / w;
let py = (h[1][0] * x + h[1][1] * y + h[1][2]) / w;
points.push(Point2::new(px, py));
}
}
points
}
fn main() {
let points = warped_grid(6, 5);
println!("input: {} perspective-warped points\n", points.len());
let detection = match detect_regular_grid(&points) {
Ok(grid) => grid,
Err(RegularGridError::TooFewPoints { found }) => {
eprintln!("need at least 4 points for a 2x2 seed, got {found}");
return;
}
Err(RegularGridError::DegeneratePointCloud) => {
eprintln!("cloud is degenerate (coincident points / no spread)");
return;
}
Err(RegularGridError::NoGridFound) => {
eprintln!("no square lattice could be seeded from the cloud");
return;
}
Err(other) => {
eprintln!("detection failed: {other}");
return;
}
};
println!("inferred grid geometry");
println!(" cell_size : {:.2} px", detection.cell_size);
println!(
" axis_i : ({:+.3}, {:+.3}) (+i direction in pixel space)",
detection.axis_i.x, detection.axis_i.y
);
println!(
" axis_j : ({:+.3}, {:+.3}) (+j direction in pixel space)\n",
detection.axis_j.x, detection.axis_j.y
);
println!("labelled corners: {}", detection.points.len());
for p in &detection.points {
println!(
" (i={:>2}, j={:>2}) -> ({:7.2}, {:7.2}) [input #{}]",
p.grid.0, p.grid.1, p.position.x, p.position.y, p.source_index
);
}
let map = detection.labelled_map();
if let Some(&idx) = map.get(&(0, 0)) {
println!("\norigin (0, 0) is input point #{idx}");
}
let s = &detection.stats;
println!("\nstats");
println!(" input_points : {}", s.input_points);
println!(" components_found : {}", s.components_found);
println!(" labelled_before_prune: {}", s.labelled_before_prune);
println!(" pruned_disconnected : {}", s.pruned_disconnected);
println!(" dropped_by_validation: {}", s.dropped_by_validation);
println!(" canonicalized : {}", s.canonicalized);
}