From 717b74fd998ea82f9462e5ef8b87913bdc7be816 Mon Sep 17 00:00:00 2001 From: Henry Schimke Date: Wed, 8 Mar 2023 12:46:52 -0600 Subject: [PATCH] cleanup point transform code --- src/aztec/detector.rs | 37 ++++----- src/common/PerspectiveTransformTestCase.rs | 37 ++++++--- src/common/default_grid_sampler.rs | 39 +++++---- src/common/grid_sampler.rs | 50 ++++++----- src/common/perspective_transform.rs | 83 +++++++++---------- src/common/quad.rs | 14 ++-- .../detector/datamatrix_detector.rs | 19 +++-- .../zxing_cpp_detector/cpp_new_detector.rs | 22 ++--- src/maxicode/detector.rs | 13 ++- src/qrcode/detector/qrcode_detector.rs | 34 +++++--- 10 files changed, 190 insertions(+), 158 deletions(-) diff --git a/src/aztec/detector.rs b/src/aztec/detector.rs index 145d817..b0bc4a2 100644 --- a/src/aztec/detector.rs +++ b/src/aztec/detector.rs @@ -18,7 +18,7 @@ use crate::{ common::{ detector::WhiteRectangleDetector, reedsolomon::{self, ReedSolomonDecoder}, - BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral, + BitMatrix, DefaultGridSampler, GridSampler, Quadrilateral, Result, }, exceptions::Exceptions, point, Point, @@ -89,16 +89,15 @@ impl<'a> Detector<'_> { // 3. Get the size of the matrix and other parameters from the bull's eye self.extractParameters(&bulls_eye_corners)?; -let src_quad = Quadrilateral::new(bulls_eye_corners[self.shift as usize % 4], - bulls_eye_corners[(self.shift as usize + 1) % 4], - bulls_eye_corners[(self.shift as usize + 2) % 4], - bulls_eye_corners[(self.shift as usize + 3) % 4],); + let src_quad = Quadrilateral::new( + bulls_eye_corners[self.shift as usize % 4], + bulls_eye_corners[(self.shift as usize + 1) % 4], + bulls_eye_corners[(self.shift as usize + 2) % 4], + bulls_eye_corners[(self.shift as usize + 3) % 4], + ); // 4. Sample the grid - let bits = self.sample_grid( - self.image, - src_quad - )?; + let bits = self.sample_grid(self.image, src_quad)?; // 5. Get the corners of the matrix. let corners = self.get_matrix_corner_points(&bulls_eye_corners); @@ -456,25 +455,21 @@ let src_quad = Quadrilateral::new(bulls_eye_corners[self.shift as usize % 4], * topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the * diagonal just outside the bull's eye. */ - fn sample_grid( - &self, - image: &BitMatrix, - quad: Quadrilateral, - ) -> Result { + fn sample_grid(&self, image: &BitMatrix, quad: Quadrilateral) -> Result { let sampler = DefaultGridSampler::default(); let dimension = self.get_dimension(); let low = dimension as f32 / 2.0 - self.nb_center_layers as f32; let high = dimension as f32 / 2.0 + self.nb_center_layers as f32; - let dst = Quadrilateral::new(point(low,low), point(high,low), point(high,high), point(low,high)); + let dst = Quadrilateral::new( + point(low, low), + point(high, low), + point(high, high), + point(low, high), + ); - sampler.sample_grid_detailed( - image, - dimension, - dimension, - dst, quad - ) + sampler.sample_grid_detailed(image, dimension, dimension, dst, quad) } /** diff --git a/src/common/PerspectiveTransformTestCase.rs b/src/common/PerspectiveTransformTestCase.rs index c804d53..f87354d 100644 --- a/src/common/PerspectiveTransformTestCase.rs +++ b/src/common/PerspectiveTransformTestCase.rs @@ -27,11 +27,16 @@ use crate::point; // public final class PerspectiveTransformTestCase extends Assert { use super::{PerspectiveTransform, Quadrilateral}; -static EPSILON: f32 = 1.0E-4f32; +static EPSILON: f32 = 1.0E-4_f32; #[test] fn test_square_to_quadrilateral() { - let square = Quadrilateral::new(point(2.0, 3.0), point(10.0, 3.0), point(16.0, 15.0), point(4.0,9.0)); + let square = Quadrilateral::new( + point(2.0, 3.0), + point(10.0, 3.0), + point(16.0, 15.0), + point(4.0, 9.0), + ); let pt = PerspectiveTransform::squareToQuadrilateral(square); assert_point_equals(2.0, 3.0, 0.0, 0.0, &pt); assert_point_equals(10.0, 4.0, 1.0, 0.0, &pt); @@ -43,10 +48,20 @@ fn test_square_to_quadrilateral() { #[test] fn test_quadrilateral_to_quadrilateral() { - let quad1 = Quadrilateral::new(point(2.0, 3.0), point(10.0, 4.0), point(16.0, 15.0), point(4.0, 9.0)); - let quad2 = Quadrilateral::new(point(103.0, 110.0), point(300.0, 120.0), point(290.0, 270.0), point(150.0,280.0)); - let pt = PerspectiveTransform::quadrilateralToQuadrilateral(quad1, quad2); - + let quad1 = Quadrilateral::new( + point(2.0, 3.0), + point(10.0, 4.0), + point(16.0, 15.0), + point(4.0, 9.0), + ); + let quad2 = Quadrilateral::new( + point(103.0, 110.0), + point(300.0, 120.0), + point(290.0, 270.0), + point(150.0, 280.0), + ); + let pt = PerspectiveTransform::quadrilateralToQuadrilateral(quad1, quad2).expect("transform"); + assert_point_equals(103.0, 110.0, 2.0, 3.0, &pt); assert_point_equals(300.0, 120.0, 10.0, 4.0, &pt); assert_point_equals(290.0, 270.0, 16.0, 15.0, &pt); @@ -62,19 +77,19 @@ fn assert_point_equals( source_y: f32, pt: &PerspectiveTransform, ) { - let mut points = [source_x, source_y]; + let mut points = [point(source_x, source_y)]; pt.transform_points_single(&mut points); assert!( - (expected_x - points[0] < EPSILON || points[0] - expected_x < EPSILON), + (expected_x - points[0].x < EPSILON || points[0].x - expected_x < EPSILON), "{} - {}", expected_x, - points[0] + points[0].x ); assert!( - (expected_y - points[1] < EPSILON || points[1] - expected_y < EPSILON), + (expected_y - points[0].y < EPSILON || points[0].y - expected_y < EPSILON), "{} - {}", expected_y, - points[1] + points[0].y ); // assert_eq!( expectedX, points[0]); diff --git a/src/common/default_grid_sampler.rs b/src/common/default_grid_sampler.rs index a2855b3..94964d7 100644 --- a/src/common/default_grid_sampler.rs +++ b/src/common/default_grid_sampler.rs @@ -18,8 +18,8 @@ // import com.google.zxing.NotFoundException; -use crate::{common::Result}; -use crate::Exceptions; +use crate::common::Result; +use crate::{Exceptions, Point}; use super::{BitMatrix, GridSampler, PerspectiveTransform, Quadrilateral, SamplerControl}; @@ -36,13 +36,16 @@ impl GridSampler for DefaultGridSampler { dimensionX: u32, dimensionY: u32, dst: Quadrilateral, - src:Quadrilateral + src: Quadrilateral, ) -> Result { - let transform = PerspectiveTransform::quadrilateralToQuadrilateral( - dst, src, - ); + let transform = PerspectiveTransform::quadrilateralToQuadrilateral(dst, src)?; - self.sample_grid(image, dimensionX, dimensionY, &[SamplerControl::new(dimensionX, dimensionY, transform)]) + self.sample_grid( + image, + dimensionX, + dimensionY, + &[SamplerControl::new(dimensionX, dimensionY, transform)], + ) } fn sample_grid( @@ -50,13 +53,13 @@ impl GridSampler for DefaultGridSampler { image: &BitMatrix, dimensionX: u32, dimensionY: u32, - controls: &[SamplerControl] + controls: &[SamplerControl], ) -> Result { if dimensionX == 0 || dimensionY == 0 { return Err(Exceptions::NOT_FOUND); } let mut bits = BitMatrix::new(dimensionX, dimensionY)?; - let mut points = vec![0.0; 2 * dimensionX as usize]; + let mut points = vec![Point::default(); dimensionX as usize]; for y in 0..dimensionY { // for (int y = 0; y < dimensionY; y++) { let max = points.len(); @@ -64,11 +67,15 @@ impl GridSampler for DefaultGridSampler { let mut x = 0; while x < max { // for (int x = 0; x < max; x += 2) { - points[x] = (x as f32 / 2.0) + 0.5; - points[x + 1] = i_value; - x += 2; + points[x].x = (x as f32) + 0.5; + points[x].y = i_value; + x += 1; } - controls.first().unwrap().transform.transform_points_single(&mut points); + controls + .first() + .unwrap() + .transform + .transform_points_single(&mut points); // Quick check to see if points transformed to something inside the image; // sufficient to check the endpoints self.checkAndNudgePoints(image, &mut points)?; @@ -83,15 +90,15 @@ impl GridSampler for DefaultGridSampler { // )); // } if image - .try_get(points[x] as u32, points[x + 1] as u32) + .try_get(points[x].x as u32, points[x].y as u32) .ok_or(Exceptions::not_found_with( "index out of bounds, see documentation in file for explanation", ))? { // Black(-ish) pixel - bits.set(x as u32 / 2, y); + bits.set(x as u32, y); } - x += 2; + x += 1; } // } catch (ArrayIndexOutOfBoundsException aioobe) { // // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting diff --git a/src/common/grid_sampler.rs b/src/common/grid_sampler.rs index aeea7c2..7fc5a4e 100644 --- a/src/common/grid_sampler.rs +++ b/src/common/grid_sampler.rs @@ -19,7 +19,7 @@ // import com.google.zxing.NotFoundException; use crate::{common::Result, Point}; -use crate::{Exceptions, point}; +use crate::{point, Exceptions}; use super::{BitMatrix, PerspectiveTransform, Quadrilateral}; @@ -94,7 +94,7 @@ pub trait GridSampler { dimensionX: u32, dimensionY: u32, dst: Quadrilateral, - src:Quadrilateral + src: Quadrilateral, ) -> Result; fn sample_grid( @@ -102,7 +102,7 @@ pub trait GridSampler { image: &BitMatrix, dimensionX: u32, dimensionY: u32, - controls: &[SamplerControl] + controls: &[SamplerControl], ) -> Result; /** @@ -120,7 +120,7 @@ pub trait GridSampler { * @param points actual points in x1,y1,...,xn,yn form * @throws NotFoundException if an endpoint is lies outside the image boundaries */ - fn checkAndNudgePoints(&self, image: &BitMatrix, points: &mut [f32]) -> Result<()> { + fn checkAndNudgePoints(&self, image: &BitMatrix, points: &mut [Point]) -> Result<()> { let width = image.getWidth(); let height = image.getHeight(); // Check and nudge points from start until we see some that are OK: @@ -129,54 +129,54 @@ pub trait GridSampler { let mut offset = 0; while offset < max_offset && nudged { // for (int offset = 0; offset < maxOffset && nudged; offset += 2) { - let x = points[offset] as i32; - let y = points[offset + 1] as i32; + let x = points[offset].x as i32; + let y = points[offset].y as i32; if x < -1 || x > width as i32 || y < -1 || y > height as i32 { return Err(Exceptions::NOT_FOUND); } nudged = false; if x == -1 { - points[offset] = 0.0; + points[offset].x = 0.0; nudged = true; } else if x == width as i32 { - points[offset] = width as f32 - 1.0; + points[offset].x = width as f32 - 1.0; nudged = true; } if y == -1 { - points[offset + 1] = 0.0; + points[offset].y = 0.0; nudged = true; } else if y == height as i32 { - points[offset + 1] = height as f32 - 1.0; + points[offset].y = height as f32 - 1.0; nudged = true; } - offset += 2; + offset += 1; } // Check and nudge points from end: nudged = true; - let mut offset = points.len() as isize - 2; + let mut offset = points.len() as isize - 1; while offset >= 0 && nudged { // for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) { - let x = points[offset as usize] as i32; - let y = points[offset as usize + 1] as i32; + let x = points[offset as usize].x as i32; + let y = points[offset as usize].y as i32; if x < -1 || x > width as i32 || y < -1 || y > height as i32 { return Err(Exceptions::NOT_FOUND); } nudged = false; if x == -1 { - points[offset as usize] = 0.0; + points[offset as usize].x = 0.0; nudged = true; } else if x == width as i32 { - points[offset as usize] = width as f32 - 1.0; + points[offset as usize].x = width as f32 - 1.0; nudged = true; } if y == -1 { - points[offset as usize + 1] = 0.0; + points[offset as usize].y = 0.0; nudged = true; } else if y == height as i32 { - points[offset as usize + 1] = height as f32 - 1.0; + points[offset as usize].y = height as f32 - 1.0; nudged = true; } - offset += -2; + offset += -1; } Ok(()) } @@ -185,11 +185,15 @@ pub trait GridSampler { pub struct SamplerControl { pub p0: Point, pub p1: Point, - pub transform: PerspectiveTransform + pub transform: PerspectiveTransform, } impl SamplerControl { - pub fn new( width: u32, height: u32, transform: PerspectiveTransform ) -> Self { - Self{ p0: point(0.0, 0.0), p1: point(width as f32, height as f32), transform } + pub fn new(width: u32, height: u32, transform: PerspectiveTransform) -> Self { + Self { + p0: point(0.0, 0.0), + p1: point(width as f32, height as f32), + transform, + } } -} \ No newline at end of file +} diff --git a/src/common/perspective_transform.rs b/src/common/perspective_transform.rs index a7038f2..5e42be3 100644 --- a/src/common/perspective_transform.rs +++ b/src/common/perspective_transform.rs @@ -18,7 +18,7 @@ use std::ops::Mul; -use crate::point; +use crate::{common::Result, point, Exceptions, Point}; use super::Quadrilateral; @@ -68,41 +68,27 @@ impl PerspectiveTransform { } #[allow(clippy::too_many_arguments)] - pub fn quadrilateralToQuadrilateral( - dst: Quadrilateral, - src: Quadrilateral - ) -> Self { - + pub fn quadrilateralToQuadrilateral(dst: Quadrilateral, src: Quadrilateral) -> Result { + if !src.is_convex() || !dst.is_convex() { + return Err(Exceptions::ILLEGAL_STATE); + } // let q_to_s = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3); // let s_to_q = // PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); let q_to_s = PerspectiveTransform::quadrilateralToSquare(dst); - let s_to_q = - PerspectiveTransform::squareToQuadrilateral(src); - s_to_q * q_to_s + let s_to_q = PerspectiveTransform::squareToQuadrilateral(src); + Ok(s_to_q * q_to_s) } - pub fn transform_points_single(&self, points: &mut [f32]) { - let a11 = self.a11; - let a12 = self.a12; - let a13 = self.a13; - let a21 = self.a21; - let a22 = self.a22; - let a23 = self.a23; - let a31 = self.a31; - let a32 = self.a32; - let a33 = self.a33; - let maxI = points.len() - 1; // points.length must be even - let mut i = 0; - while i < maxI { + pub fn transform_points_single(&self, points: &mut [Point]) { + for point in points.iter_mut() { // for (int i = 0; i < maxI; i += 2) { - let x = points[i]; - let y = points[i + 1]; - let denominator = a13 * x + a23 * y + a33; - points[i] = (a11 * x + a21 * y + a31) / denominator; - points[i + 1] = (a12 * x + a22 * y + a32) / denominator; - i += 2; + let x = point.x; + let y = point.y; + let denominator = self.a13 * x + self.a23 * y + self.a33; + point.x = (self.a11 * x + self.a21 * y + self.a31) / denominator; + point.y = (self.a12 * x + self.a22 * y + self.a32) / denominator; } } @@ -118,23 +104,30 @@ impl PerspectiveTransform { } #[allow(clippy::too_many_arguments)] - pub fn squareToQuadrilateral( - square: Quadrilateral - ) -> Self { - let [p0, p1, p2, p3 ] = square.0; - - let d3 = p0 - p1 + p2 - p3; - if d3 == point(0.0,0.0) { - // Affine - PerspectiveTransform::new(p1.x - p0.x, p2.x - p1.x, p0.x, p1.y - p0.y, p2.y - p1.y, p0.y, 0.0, 0.0, 1.0) - } else { + pub fn squareToQuadrilateral(square: Quadrilateral) -> Self { + let [p0, p1, p2, p3] = square.0; -let d1 = p1 - p2; -let d2 = p3 - p2; + let d3 = p0 - p1 + p2 - p3; + if d3 == point(0.0, 0.0) { + // Affine + PerspectiveTransform::new( + p1.x - p0.x, + p2.x - p1.x, + p0.x, + p1.y - p0.y, + p2.y - p1.y, + p0.y, + 0.0, + 0.0, + 1.0, + ) + } else { + let d1 = p1 - p2; + let d2 = p3 - p2; let denominator = d1.cross(d2); - let a13 = (d3.x * d2.y - d2.x * d3.y) / denominator; - let a23 = (d1.x * d3.y - d3.x * d1.y) / denominator; + let a13 = d3.cross(d2) / denominator; + let a23 = d1.cross(d3) / denominator; PerspectiveTransform::new( p1.x - p0.x + a13 * p1.x, p3.x - p0.x + a23 * p3.x, @@ -150,9 +143,7 @@ let d2 = p3 - p2; } #[allow(clippy::too_many_arguments)] - pub fn quadrilateralToSquare( - quad: Quadrilateral - ) -> Self { + pub fn quadrilateralToSquare(quad: Quadrilateral) -> Self { // Here, the adjoint serves as the inverse PerspectiveTransform::squareToQuadrilateral(quad).buildAdjoint() } @@ -189,4 +180,4 @@ impl Mul for PerspectiveTransform { self.a13 * rhs.a31 + self.a23 * rhs.a32 + self.a33 * rhs.a33, ) } -} \ No newline at end of file +} diff --git a/src/common/quad.rs b/src/common/quad.rs index 5b8c4cf..9873d8b 100644 --- a/src/common/quad.rs +++ b/src/common/quad.rs @@ -10,8 +10,8 @@ impl Quadrilateral { // using Point = T; #[allow(dead_code)] - pub fn new(tl:Point, tr: Point, br: Point, bl: Point) -> Self { - Self([tl,tr,br,bl]) + pub fn new(tl: Point, tr: Point, br: Point, bl: Point) -> Self { + Self([tl, tr, br, bl]) } // pub fn with_f32( tl:f32, tr:f32, br:f32, bl:f32) -> Self { // Self([tl, tr,br, bl ]) @@ -124,11 +124,11 @@ impl Quadrilateral { let d2 = self.0[i] - self.0[(i + 1) % N]; let cp = d1.cross(d2); - m = if m.abs() > cp { cp } else { m.abs() }; + // m = if m.abs() > cp { cp } else { m.abs() }; - M = if M.abs() > cp { M.abs() } else { cp }; - // m = std::cmp::min((m).abs(), cp); - // M = std::cmp::max((M).abs(), cp); + // M = if M.abs() > cp { M.abs() } else { cp }; + m = f32::min((m).abs(), cp); + M = f32::max((M).abs(), cp); if i == 0 { sign = cp > 0.0; @@ -214,4 +214,4 @@ impl Default for Quadrilateral { fn default() -> Self { Self([Point { x: 0.0, y: 0.0 }; 4]) } -} \ No newline at end of file +} diff --git a/src/datamatrix/detector/datamatrix_detector.rs b/src/datamatrix/detector/datamatrix_detector.rs index 9e34682..88a973c 100644 --- a/src/datamatrix/detector/datamatrix_detector.rs +++ b/src/datamatrix/detector/datamatrix_detector.rs @@ -16,7 +16,8 @@ use crate::{ common::{ - detector::WhiteRectangleDetector, BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral, + detector::WhiteRectangleDetector, BitMatrix, DefaultGridSampler, GridSampler, + Quadrilateral, Result, }, point, Exceptions, Point, }; @@ -334,15 +335,15 @@ impl<'a> Detector<'_> { ) -> Result { let sampler = DefaultGridSampler::default(); - let dst = Quadrilateral::new(point(0.5, 0.5), point(dimensionX as f32 - 0.5, 0.5), point(dimensionX as f32 - 0.5,dimensionY as f32 - 0.5), point(0.5, dimensionY as f32 - 0.5)); - let src = Quadrilateral::new(topRight, topLeft,bottomRight, bottomLeft); + let dst = Quadrilateral::new( + point(0.5, 0.5), + point(dimensionX as f32 - 0.5, 0.5), + point(dimensionX as f32 - 0.5, dimensionY as f32 - 0.5), + point(0.5, dimensionY as f32 - 0.5), + ); + let src = Quadrilateral::new(topRight, topLeft, bottomRight, bottomLeft); - sampler.sample_grid_detailed( - image, - dimensionX, - dimensionY, - dst, src - ) + sampler.sample_grid_detailed(image, dimensionX, dimensionY, dst, src) } /** diff --git a/src/datamatrix/detector/zxing_cpp_detector/cpp_new_detector.rs b/src/datamatrix/detector/zxing_cpp_detector/cpp_new_detector.rs index 958e1f1..761cba3 100644 --- a/src/datamatrix/detector/zxing_cpp_detector/cpp_new_detector.rs +++ b/src/datamatrix/detector/zxing_cpp_detector/cpp_new_detector.rs @@ -14,13 +14,14 @@ macro_rules! CHECK { use std::{cell::RefCell, rc::Rc}; use crate::{ - common::{BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral}, + common::{BitMatrix, DefaultGridSampler, GridSampler, Quadrilateral, Result}, datamatrix::detector::{ zxing_cpp_detector::{util::intersect, BitMatrixCursor, RegressionLine}, DatamatrixDetectorResult, }, + point, qrcode::encoder::ByteMatrix, - Exceptions, Point, point, + Exceptions, Point, }; use super::{DMRegressionLine, EdgeTracer}; @@ -212,15 +213,16 @@ fn Scan( let grid_sampler = DefaultGridSampler::default(); // let transform = PerspectiveTransform::quadrilateralToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3, x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p); -let dst = Quadrilateral::new(point(0.0,0.0), point(dimT as f32, 0.0), point(dimT as f32, dimR as f32), point(0.0, dimR as f32)); -let src = sourcePoints; - - let res = grid_sampler.sample_grid_detailed( - startTracer.img, - dimT as u32, - dimR as u32, - dst, src + let dst = Quadrilateral::new( + point(0.0, 0.0), + point(dimT as f32, 0.0), + point(dimT as f32, dimR as f32), + point(0.0, dimR as f32), ); + let src = sourcePoints; + + let res = + grid_sampler.sample_grid_detailed(startTracer.img, dimT as u32, dimR as u32, dst, src); // let res = grid_sampler.sample_grid(startTracer.img, dimT as u32, dimR as u32, &transform); diff --git a/src/maxicode/detector.rs b/src/maxicode/detector.rs index c03373c..18b3244 100644 --- a/src/maxicode/detector.rs +++ b/src/maxicode/detector.rs @@ -2,7 +2,9 @@ use num::integer::Roots; use crate::{ - common::{BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler, Result, Quadrilateral}, + common::{ + BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler, Quadrilateral, Result, + }, point, Exceptions, Point, }; @@ -346,9 +348,12 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result Detector<'_> { sourceBottomRightY = dimMinusThree; } - let dst = Quadrilateral::new(point(3.5, - 3.5), point(dimMinusThree, - 3.5), point(sourceBottomRightX, - sourceBottomRightY), point(3.5, - dimMinusThree)); - let src = Quadrilateral::new( topLeft, topRight, point(bottomRightX, bottomRightY), bottomLeft); + let dst = Quadrilateral::new( + point(3.5, 3.5), + point(dimMinusThree, 3.5), + point(sourceBottomRightX, sourceBottomRightY), + point(3.5, dimMinusThree), + ); + let src = Quadrilateral::new( + topLeft, + topRight, + point(bottomRightX, bottomRightY), + bottomLeft, + ); - Some(PerspectiveTransform::quadrilateralToQuadrilateral( - dst, src - )) + PerspectiveTransform::quadrilateralToQuadrilateral(dst, src).ok() } fn sampleGrid( @@ -211,7 +218,12 @@ impl<'a> Detector<'_> { dimension: u32, ) -> Result { let sampler = DefaultGridSampler::default(); - sampler.sample_grid(image, dimension, dimension, &[SamplerControl::new(dimension, dimension, transform)]) + sampler.sample_grid( + image, + dimension, + dimension, + &[SamplerControl::new(dimension, dimension, transform)], + ) } /**