use crate::{sample_bilinear_u8, GrayImage, GrayImageView};
use nalgebra::Point2;
pub use projective_grid::expert::geometry::{
estimate_homography as estimate_homography_rect_to_img, estimate_homography_with_quality,
homography_from_4pt, homography_from_4pt_with_quality, Homography, HomographyQuality,
};
pub fn warp_perspective_gray(
src: &GrayImageView<'_>,
h_img_from_rect: Homography,
out_w: usize,
out_h: usize,
) -> GrayImage {
let mut out = vec![0u8; out_w * out_h];
for y in 0..out_h {
for x in 0..out_w {
let pr = Point2::new(x as f32 + 0.5, y as f32 + 0.5);
let pi = h_img_from_rect.apply(pr);
let v = sample_bilinear_u8(src, pi.x, pi.y);
out[y * out_w + x] = v;
}
}
GrayImage {
width: out_w,
height: out_h,
data: out,
}
}
#[cfg(test)]
mod tests {
use super::*;
use nalgebra::Matrix3;
fn assert_close(a: Point2<f32>, b: Point2<f32>, tol: f32) {
let dx = (a.x - b.x).abs();
let dy = (a.y - b.y).abs();
assert!(
dx < tol && dy < tol,
"expected ({:.6},{:.6}) ~ ({:.6},{:.6}) within {}",
a.x,
a.y,
b.x,
b.y,
tol
);
}
#[test]
fn reexported_estimate_alias_recovers_clean_grid() {
let ground_truth = Homography::new(Matrix3::new(
1.0, 0.2, 12.0, -0.1, 0.9, 6.0, 0.0006, 0.0004, 1.0,
));
let rect: Vec<Point2<f32>> = (0..3)
.flat_map(|y| (0..3).map(move |x| Point2::new(x as f32 * 40.0, y as f32 * 50.0)))
.collect();
let img: Vec<Point2<f32>> = rect.iter().map(|&p| ground_truth.apply(p)).collect();
let estimated = estimate_homography_rect_to_img(&rect, &img).expect("estimate");
for p in [
Point2::new(0.0_f32, 0.0),
Point2::new(60.0, 40.0),
Point2::new(80.0, 90.0),
] {
assert_close(estimated.apply(p), ground_truth.apply(p), 1e-3);
}
}
}