ported changes from c++ f80a9b923a14827cc78bb96703676c14ac61c1ed

This commit is contained in:
Henry Schimke
2023-05-30 16:11:42 -05:00
parent 07c1f17766
commit 22cabc2975
2 changed files with 25 additions and 17 deletions

View File

@@ -19,7 +19,7 @@
// import com.google.zxing.NotFoundException; // import com.google.zxing.NotFoundException;
use crate::common::Result; use crate::common::Result;
use crate::{point_f, Exceptions, Point}; use crate::{point, point_f, Exceptions, Point};
use super::{BitMatrix, GridSampler, SamplerControl}; use super::{BitMatrix, GridSampler, SamplerControl};
@@ -42,22 +42,17 @@ impl GridSampler for DefaultGridSampler {
} }
for SamplerControl { p0, p1, transform } in controls { for SamplerControl { p0, p1, transform } in controls {
// To deal with remaining examples (see #251 and #267) of "numercial instabilities" that have not been // Precheck the corners of every roi to bail out early if the grid is "obviously" not completely inside the image
// prevented with the Quadrilateral.h:IsConvex() check, we check for all boundary points of the grid to let isInside = |x: f32, y: f32| {
// be inside. image.is_in(transform.transform_point(Point::centered(point(x, y))))
let isInside = };
|p: Point| -> bool { image.is_in(transform.transform_point(p.centered())) }; if (!transform.isValid()
for y in (p0.y as i32)..(p1.y as i32) { || !isInside(p0.x, p0.y)
// for (int y = y0; y < y1; ++y) || !isInside(p1.x - 1.0, p0.y)
if !isInside(point_f(p0.x, y as f32)) || !isInside(point_f(p1.x - 1.0, y as f32)) { || !isInside(p1.x - 1.0, p1.y - 1.0)
return Err(Exceptions::NOT_FOUND); || !isInside(p0.x, p1.y - 1.0))
} {
} return Err(Exceptions::NOT_FOUND);
for x in (p0.x as i32)..(p1.x as i32) {
// for (int x = x0; x < x1; ++x)
if !isInside(point_f(x as f32, p0.y)) || !isInside(point_f(x as f32, p1.y - 1.0)) {
return Err(Exceptions::NOT_FOUND);
}
} }
} }
@@ -73,6 +68,15 @@ impl GridSampler for DefaultGridSampler {
if image.get_point(p) { if image.get_point(p) {
bits.set(x as u32, y as u32); bits.set(x as u32, y as u32);
} }
// Due to a "numerical instability" in the PerspectiveTransform generation/application it has been observed
// that even though all boundary grid points get projected inside the image, it can still happen that an
// inner grid points is not. See #563. A true perspective transformation cannot have this property.
// The following check takes 100% care of the issue and turned out to be less of a performance impact than feared.
// TODO: Check some mathematical/numercial property of mod2Pix to determine if it is a perspective transforation.
if (!image.is_in(p)) {
return Err(Exceptions::NOT_FOUND);
}
} }
} }
} }

View File

@@ -176,6 +176,10 @@ impl PerspectiveTransform {
self.a11 * self.a22 - self.a12 * self.a21, self.a11 * self.a22 - self.a12 * self.a21,
) )
} }
pub fn isValid(&self) -> bool {
!self.a33.is_nan()
}
} }
impl Mul for PerspectiveTransform { impl Mul for PerspectiveTransform {