mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 12:22:34 +00:00
Promote Quadrilateral to default
The library now uses the `Quadrilateral` struct when handling sets of four points in `GridSampler` and `PerspectiveTransform`
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
|
||||
use crate::{
|
||||
common::{
|
||||
detector::WhiteRectangleDetector, BitMatrix, DefaultGridSampler, GridSampler, Result,
|
||||
detector::WhiteRectangleDetector, BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral,
|
||||
},
|
||||
point, Exceptions, Point,
|
||||
};
|
||||
@@ -334,26 +334,14 @@ impl<'a> Detector<'_> {
|
||||
) -> Result<BitMatrix> {
|
||||
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);
|
||||
|
||||
sampler.sample_grid_detailed(
|
||||
image,
|
||||
dimensionX,
|
||||
dimensionY,
|
||||
0.5,
|
||||
0.5,
|
||||
dimensionX as f32 - 0.5,
|
||||
0.5,
|
||||
dimensionX as f32 - 0.5,
|
||||
dimensionY as f32 - 0.5,
|
||||
0.5,
|
||||
dimensionY as f32 - 0.5,
|
||||
topLeft.x,
|
||||
topLeft.y,
|
||||
topRight.x,
|
||||
topRight.y,
|
||||
bottomRight.x,
|
||||
bottomRight.y,
|
||||
bottomLeft.x,
|
||||
bottomLeft.y,
|
||||
dst, src
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,13 +14,13 @@ macro_rules! CHECK {
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
common::{BitMatrix, DefaultGridSampler, GridSampler, Result},
|
||||
common::{BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral},
|
||||
datamatrix::detector::{
|
||||
zxing_cpp_detector::{util::intersect, BitMatrixCursor, Quadrilateral, RegressionLine},
|
||||
zxing_cpp_detector::{util::intersect, BitMatrixCursor, RegressionLine},
|
||||
DatamatrixDetectorResult,
|
||||
},
|
||||
qrcode::encoder::ByteMatrix,
|
||||
Exceptions, Point,
|
||||
Exceptions, Point, point,
|
||||
};
|
||||
|
||||
use super::{DMRegressionLine, EdgeTracer};
|
||||
@@ -212,27 +212,14 @@ 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,
|
||||
0.0,
|
||||
0.0,
|
||||
dimT as f32,
|
||||
0.0,
|
||||
dimT as f32,
|
||||
dimR as f32,
|
||||
0.0,
|
||||
dimR as f32,
|
||||
sourcePoints.topLeft().x,
|
||||
sourcePoints.topLeft().y,
|
||||
sourcePoints.topRight().x,
|
||||
sourcePoints.topRight().y,
|
||||
sourcePoints.bottomRight().x,
|
||||
sourcePoints.bottomRight().y,
|
||||
sourcePoints.bottomLeft().x,
|
||||
sourcePoints.bottomLeft().y,
|
||||
dst, src
|
||||
);
|
||||
|
||||
// let res = grid_sampler.sample_grid(startTracer.img, dimT as u32, dimR as u32, &transform);
|
||||
|
||||
@@ -3,7 +3,6 @@ mod cpp_new_detector;
|
||||
mod direction;
|
||||
mod dm_regression_line;
|
||||
mod edge_tracer;
|
||||
mod quad;
|
||||
mod regression_line;
|
||||
mod step_result;
|
||||
pub(self) mod util;
|
||||
@@ -14,7 +13,6 @@ pub use cpp_new_detector::detect;
|
||||
pub(self) use direction::*;
|
||||
pub(self) use dm_regression_line::*;
|
||||
pub(self) use edge_tracer::*;
|
||||
pub(self) use quad::*;
|
||||
pub(self) use regression_line::*;
|
||||
pub(self) use step_result::*;
|
||||
pub(self) use value::*;
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
use crate::Point;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Quadrilateral([Point; 4]);
|
||||
|
||||
impl Quadrilateral {
|
||||
// using Base = std::array<T, 4>;
|
||||
// using Base::at;
|
||||
// public:
|
||||
// using Point = T;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
Self([Point { x: 0.0, y: 0.0 }; 4])
|
||||
}
|
||||
// pub fn with_f32( tl:f32, tr:f32, br:f32, bl:f32) -> Self {
|
||||
// Self([tl, tr,br, bl ])
|
||||
// }
|
||||
|
||||
pub fn with_points(tl: Point, tr: Point, br: Point, bl: Point) -> Self {
|
||||
Self([tl, tr, br, bl])
|
||||
}
|
||||
|
||||
pub fn topLeft(&self) -> &Point {
|
||||
&self.0[0]
|
||||
} //const noexcept { return at(0); }
|
||||
pub fn topRight(&self) -> &Point {
|
||||
&self.0[1]
|
||||
} //const noexcept { return at(1); }
|
||||
pub fn bottomRight(&self) -> &Point {
|
||||
&self.0[2]
|
||||
} //const noexcept { return at(2); }
|
||||
pub fn bottomLeft(&self) -> &Point {
|
||||
&self.0[3]
|
||||
} //const noexcept { return at(3); }
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn orientation(&self) -> f64 {
|
||||
let centerLine =
|
||||
(*self.topRight() + *self.bottomRight()) - (*self.topLeft() + *self.bottomLeft());
|
||||
if (centerLine == Point { x: 0.0, y: 0.0 }) {
|
||||
return 0.0;
|
||||
}
|
||||
let centerLineF = Point::normalized(centerLine);
|
||||
f32::atan2(centerLineF.y, centerLineF.x).into()
|
||||
}
|
||||
pub fn points(&self) -> &[Point] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn Rectangle(width: i32, height: i32, margin: Option<i32>) -> Quadrilateral {
|
||||
let margin = if let Some(m) = margin { m } else { 0 };
|
||||
|
||||
Quadrilateral([
|
||||
Point {
|
||||
x: margin as f32,
|
||||
y: margin as f32,
|
||||
},
|
||||
Point {
|
||||
x: width as f32 - margin as f32,
|
||||
y: margin as f32,
|
||||
},
|
||||
Point {
|
||||
x: width as f32 - margin as f32,
|
||||
y: height as f32 - margin as f32,
|
||||
},
|
||||
Point {
|
||||
x: margin as f32,
|
||||
y: height as f32 - margin as f32,
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn CenteredSquare(size: i32) -> Quadrilateral {
|
||||
Scale(
|
||||
&Quadrilateral([
|
||||
Point { x: -1.0, y: -1.0 },
|
||||
Point { x: 1.0, y: -1.0 },
|
||||
Point { x: 1.0, y: 1.0 },
|
||||
Point { x: -1.0, y: 1.0 },
|
||||
]),
|
||||
size / 2,
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn Line(y: i32, xStart: i32, xStop: i32) -> Quadrilateral {
|
||||
Quadrilateral([
|
||||
Point {
|
||||
x: xStart as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
Point {
|
||||
x: xStop as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
Point {
|
||||
x: xStop as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
Point {
|
||||
x: xStart as f32,
|
||||
y: y as f32,
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn IsConvex(poly: &Quadrilateral) -> bool {
|
||||
let N = poly.0.len();
|
||||
let mut sign = false;
|
||||
|
||||
let mut m = f32::INFINITY;
|
||||
let mut M = 0.0_f32;
|
||||
|
||||
for i in 0..N
|
||||
// for(int i = 0; i < N; i++)
|
||||
{
|
||||
let d1 = poly.0[(i + 2) % N] - poly.0[(i + 1) % N];
|
||||
let d2 = poly.0[i] - poly.0[(i + 1) % N];
|
||||
let cp = d1.cross(d2);
|
||||
|
||||
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);
|
||||
|
||||
if i == 0 {
|
||||
sign = cp > 0.0;
|
||||
} else if sign != (cp > 0.0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// It turns out being convex is not enough to prevent a "numerical instability"
|
||||
// that can cause the corners being projected inside the image boundaries but
|
||||
// some points near the corners being projected outside. This has been observed
|
||||
// where one corner is almost in line with two others. The M/m ratio is below 2
|
||||
// for the complete existing sample set. For very "skewed" QRCodes a value of
|
||||
// around 3 is realistic. A value of 14 has been observed to trigger the
|
||||
// instability.
|
||||
M / m < 4.0
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn Scale(q: &Quadrilateral, factor: i32) -> Quadrilateral {
|
||||
Quadrilateral([
|
||||
q.0[0] * factor as f32,
|
||||
q.0[1] * factor as f32,
|
||||
q.0[2] * factor as f32,
|
||||
q.0[3] * factor as f32,
|
||||
])
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn Center(q: &Quadrilateral) -> Point {
|
||||
let reduced: Point = q.0.iter().sum();
|
||||
let size = q.0.len() as f32;
|
||||
reduced / size
|
||||
// return Reduce(q) / Size(q);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn RotatedCorners(q: &Quadrilateral, n: Option<i32>, mirror: Option<bool>) -> Quadrilateral {
|
||||
let n = if let Some(n) = n { n } else { 1 };
|
||||
|
||||
let mirror = if let Some(m) = mirror { m } else { false };
|
||||
|
||||
let mut res = q.clone();
|
||||
res.0.rotate_left(((n + 4) % 4) as usize);
|
||||
// std::rotate_copy(q.begin(), q.begin() + ((n + 4) % 4), q.end(), res.begin());
|
||||
if mirror {
|
||||
res.0.swap(1, 3);
|
||||
}
|
||||
// {std::swap(res[1], res[3]);}
|
||||
res
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn IsInside(p: Point, q: &Quadrilateral) -> bool {
|
||||
// Test if p is on the same side (right or left) of all polygon segments
|
||||
let mut pos = 0;
|
||||
let mut neg = 0;
|
||||
for i in 0..q.0.len()
|
||||
// for (int i = 0; i < Size(q); ++i)
|
||||
{
|
||||
if Point::cross(p - q.0[i], q.0[(i + 1) % q.0.len()] - q.0[i]) < 0.0 {
|
||||
neg += 1;
|
||||
} else {
|
||||
pos += 1;
|
||||
}
|
||||
// (cross(p - q[i], q[(i + 1) % Size(q)] - q[i]) < 0 ? neg : pos)++;
|
||||
}
|
||||
|
||||
pos == 0 || neg == 0
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn HaveIntersectingBoundingBoxes(a: &Quadrilateral, b: &Quadrilateral) -> bool {
|
||||
// TODO: this is only a quick and dirty approximation that works for the trivial standard cases
|
||||
let x = b.topRight().x < a.topLeft().x || b.topLeft().x > a.topRight().x;
|
||||
let y = b.bottomLeft().y < a.topLeft().y || b.topLeft().y > a.bottomLeft().y;
|
||||
|
||||
!(x || y)
|
||||
}
|
||||
Reference in New Issue
Block a user