mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
cleanup point transform code
This commit is contained in:
@@ -18,7 +18,7 @@ use crate::{
|
|||||||
common::{
|
common::{
|
||||||
detector::WhiteRectangleDetector,
|
detector::WhiteRectangleDetector,
|
||||||
reedsolomon::{self, ReedSolomonDecoder},
|
reedsolomon::{self, ReedSolomonDecoder},
|
||||||
BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral,
|
BitMatrix, DefaultGridSampler, GridSampler, Quadrilateral, Result,
|
||||||
},
|
},
|
||||||
exceptions::Exceptions,
|
exceptions::Exceptions,
|
||||||
point, Point,
|
point, Point,
|
||||||
@@ -89,16 +89,15 @@ impl<'a> Detector<'_> {
|
|||||||
// 3. Get the size of the matrix and other parameters from the bull's eye
|
// 3. Get the size of the matrix and other parameters from the bull's eye
|
||||||
self.extractParameters(&bulls_eye_corners)?;
|
self.extractParameters(&bulls_eye_corners)?;
|
||||||
|
|
||||||
let src_quad = Quadrilateral::new(bulls_eye_corners[self.shift as usize % 4],
|
let src_quad = Quadrilateral::new(
|
||||||
bulls_eye_corners[(self.shift as usize + 1) % 4],
|
bulls_eye_corners[self.shift as usize % 4],
|
||||||
bulls_eye_corners[(self.shift as usize + 2) % 4],
|
bulls_eye_corners[(self.shift as usize + 1) % 4],
|
||||||
bulls_eye_corners[(self.shift as usize + 3) % 4],);
|
bulls_eye_corners[(self.shift as usize + 2) % 4],
|
||||||
|
bulls_eye_corners[(self.shift as usize + 3) % 4],
|
||||||
|
);
|
||||||
|
|
||||||
// 4. Sample the grid
|
// 4. Sample the grid
|
||||||
let bits = self.sample_grid(
|
let bits = self.sample_grid(self.image, src_quad)?;
|
||||||
self.image,
|
|
||||||
src_quad
|
|
||||||
)?;
|
|
||||||
|
|
||||||
// 5. Get the corners of the matrix.
|
// 5. Get the corners of the matrix.
|
||||||
let corners = self.get_matrix_corner_points(&bulls_eye_corners);
|
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
|
* topLeft, topRight, bottomRight, and bottomLeft are the centers of the squares on the
|
||||||
* diagonal just outside the bull's eye.
|
* diagonal just outside the bull's eye.
|
||||||
*/
|
*/
|
||||||
fn sample_grid(
|
fn sample_grid(&self, image: &BitMatrix, quad: Quadrilateral) -> Result<BitMatrix> {
|
||||||
&self,
|
|
||||||
image: &BitMatrix,
|
|
||||||
quad: Quadrilateral,
|
|
||||||
) -> Result<BitMatrix> {
|
|
||||||
let sampler = DefaultGridSampler::default();
|
let sampler = DefaultGridSampler::default();
|
||||||
let dimension = self.get_dimension();
|
let dimension = self.get_dimension();
|
||||||
|
|
||||||
let low = dimension as f32 / 2.0 - self.nb_center_layers as f32;
|
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 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(
|
sampler.sample_grid_detailed(image, dimension, dimension, dst, quad)
|
||||||
image,
|
|
||||||
dimension,
|
|
||||||
dimension,
|
|
||||||
dst, quad
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -27,11 +27,16 @@ use crate::point;
|
|||||||
// public final class PerspectiveTransformTestCase extends Assert {
|
// public final class PerspectiveTransformTestCase extends Assert {
|
||||||
use super::{PerspectiveTransform, Quadrilateral};
|
use super::{PerspectiveTransform, Quadrilateral};
|
||||||
|
|
||||||
static EPSILON: f32 = 1.0E-4f32;
|
static EPSILON: f32 = 1.0E-4_f32;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_square_to_quadrilateral() {
|
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);
|
let pt = PerspectiveTransform::squareToQuadrilateral(square);
|
||||||
assert_point_equals(2.0, 3.0, 0.0, 0.0, &pt);
|
assert_point_equals(2.0, 3.0, 0.0, 0.0, &pt);
|
||||||
assert_point_equals(10.0, 4.0, 1.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]
|
#[test]
|
||||||
fn test_quadrilateral_to_quadrilateral() {
|
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 quad1 = Quadrilateral::new(
|
||||||
let quad2 = Quadrilateral::new(point(103.0, 110.0), point(300.0, 120.0), point(290.0, 270.0), point(150.0,280.0));
|
point(2.0, 3.0),
|
||||||
let pt = PerspectiveTransform::quadrilateralToQuadrilateral(quad1, quad2);
|
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(103.0, 110.0, 2.0, 3.0, &pt);
|
||||||
assert_point_equals(300.0, 120.0, 10.0, 4.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);
|
assert_point_equals(290.0, 270.0, 16.0, 15.0, &pt);
|
||||||
@@ -62,19 +77,19 @@ fn assert_point_equals(
|
|||||||
source_y: f32,
|
source_y: f32,
|
||||||
pt: &PerspectiveTransform,
|
pt: &PerspectiveTransform,
|
||||||
) {
|
) {
|
||||||
let mut points = [source_x, source_y];
|
let mut points = [point(source_x, source_y)];
|
||||||
pt.transform_points_single(&mut points);
|
pt.transform_points_single(&mut points);
|
||||||
assert!(
|
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,
|
expected_x,
|
||||||
points[0]
|
points[0].x
|
||||||
);
|
);
|
||||||
assert!(
|
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,
|
expected_y,
|
||||||
points[1]
|
points[0].y
|
||||||
);
|
);
|
||||||
|
|
||||||
// assert_eq!( expectedX, points[0]);
|
// assert_eq!( expectedX, points[0]);
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
// import com.google.zxing.NotFoundException;
|
// import com.google.zxing.NotFoundException;
|
||||||
|
|
||||||
use crate::{common::Result};
|
use crate::common::Result;
|
||||||
use crate::Exceptions;
|
use crate::{Exceptions, Point};
|
||||||
|
|
||||||
use super::{BitMatrix, GridSampler, PerspectiveTransform, Quadrilateral, SamplerControl};
|
use super::{BitMatrix, GridSampler, PerspectiveTransform, Quadrilateral, SamplerControl};
|
||||||
|
|
||||||
@@ -36,13 +36,16 @@ impl GridSampler for DefaultGridSampler {
|
|||||||
dimensionX: u32,
|
dimensionX: u32,
|
||||||
dimensionY: u32,
|
dimensionY: u32,
|
||||||
dst: Quadrilateral,
|
dst: Quadrilateral,
|
||||||
src:Quadrilateral
|
src: Quadrilateral,
|
||||||
) -> Result<BitMatrix> {
|
) -> Result<BitMatrix> {
|
||||||
let transform = PerspectiveTransform::quadrilateralToQuadrilateral(
|
let transform = PerspectiveTransform::quadrilateralToQuadrilateral(dst, src)?;
|
||||||
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(
|
fn sample_grid(
|
||||||
@@ -50,13 +53,13 @@ impl GridSampler for DefaultGridSampler {
|
|||||||
image: &BitMatrix,
|
image: &BitMatrix,
|
||||||
dimensionX: u32,
|
dimensionX: u32,
|
||||||
dimensionY: u32,
|
dimensionY: u32,
|
||||||
controls: &[SamplerControl]
|
controls: &[SamplerControl],
|
||||||
) -> Result<BitMatrix> {
|
) -> Result<BitMatrix> {
|
||||||
if dimensionX == 0 || dimensionY == 0 {
|
if dimensionX == 0 || dimensionY == 0 {
|
||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
}
|
}
|
||||||
let mut bits = BitMatrix::new(dimensionX, dimensionY)?;
|
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 y in 0..dimensionY {
|
||||||
// for (int y = 0; y < dimensionY; y++) {
|
// for (int y = 0; y < dimensionY; y++) {
|
||||||
let max = points.len();
|
let max = points.len();
|
||||||
@@ -64,11 +67,15 @@ impl GridSampler for DefaultGridSampler {
|
|||||||
let mut x = 0;
|
let mut x = 0;
|
||||||
while x < max {
|
while x < max {
|
||||||
// for (int x = 0; x < max; x += 2) {
|
// for (int x = 0; x < max; x += 2) {
|
||||||
points[x] = (x as f32 / 2.0) + 0.5;
|
points[x].x = (x as f32) + 0.5;
|
||||||
points[x + 1] = i_value;
|
points[x].y = i_value;
|
||||||
x += 2;
|
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;
|
// Quick check to see if points transformed to something inside the image;
|
||||||
// sufficient to check the endpoints
|
// sufficient to check the endpoints
|
||||||
self.checkAndNudgePoints(image, &mut points)?;
|
self.checkAndNudgePoints(image, &mut points)?;
|
||||||
@@ -83,15 +90,15 @@ impl GridSampler for DefaultGridSampler {
|
|||||||
// ));
|
// ));
|
||||||
// }
|
// }
|
||||||
if image
|
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(
|
.ok_or(Exceptions::not_found_with(
|
||||||
"index out of bounds, see documentation in file for explanation",
|
"index out of bounds, see documentation in file for explanation",
|
||||||
))?
|
))?
|
||||||
{
|
{
|
||||||
// Black(-ish) pixel
|
// Black(-ish) pixel
|
||||||
bits.set(x as u32 / 2, y);
|
bits.set(x as u32, y);
|
||||||
}
|
}
|
||||||
x += 2;
|
x += 1;
|
||||||
}
|
}
|
||||||
// } catch (ArrayIndexOutOfBoundsException aioobe) {
|
// } catch (ArrayIndexOutOfBoundsException aioobe) {
|
||||||
// // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
|
// // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
// import com.google.zxing.NotFoundException;
|
// import com.google.zxing.NotFoundException;
|
||||||
|
|
||||||
use crate::{common::Result, Point};
|
use crate::{common::Result, Point};
|
||||||
use crate::{Exceptions, point};
|
use crate::{point, Exceptions};
|
||||||
|
|
||||||
use super::{BitMatrix, PerspectiveTransform, Quadrilateral};
|
use super::{BitMatrix, PerspectiveTransform, Quadrilateral};
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ pub trait GridSampler {
|
|||||||
dimensionX: u32,
|
dimensionX: u32,
|
||||||
dimensionY: u32,
|
dimensionY: u32,
|
||||||
dst: Quadrilateral,
|
dst: Quadrilateral,
|
||||||
src:Quadrilateral
|
src: Quadrilateral,
|
||||||
) -> Result<BitMatrix>;
|
) -> Result<BitMatrix>;
|
||||||
|
|
||||||
fn sample_grid(
|
fn sample_grid(
|
||||||
@@ -102,7 +102,7 @@ pub trait GridSampler {
|
|||||||
image: &BitMatrix,
|
image: &BitMatrix,
|
||||||
dimensionX: u32,
|
dimensionX: u32,
|
||||||
dimensionY: u32,
|
dimensionY: u32,
|
||||||
controls: &[SamplerControl]
|
controls: &[SamplerControl],
|
||||||
) -> Result<BitMatrix>;
|
) -> Result<BitMatrix>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -120,7 +120,7 @@ pub trait GridSampler {
|
|||||||
* @param points actual points in x1,y1,...,xn,yn form
|
* @param points actual points in x1,y1,...,xn,yn form
|
||||||
* @throws NotFoundException if an endpoint is lies outside the image boundaries
|
* @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 width = image.getWidth();
|
||||||
let height = image.getHeight();
|
let height = image.getHeight();
|
||||||
// Check and nudge points from start until we see some that are OK:
|
// Check and nudge points from start until we see some that are OK:
|
||||||
@@ -129,54 +129,54 @@ pub trait GridSampler {
|
|||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
while offset < max_offset && nudged {
|
while offset < max_offset && nudged {
|
||||||
// for (int offset = 0; offset < maxOffset && nudged; offset += 2) {
|
// for (int offset = 0; offset < maxOffset && nudged; offset += 2) {
|
||||||
let x = points[offset] as i32;
|
let x = points[offset].x as i32;
|
||||||
let y = points[offset + 1] as i32;
|
let y = points[offset].y as i32;
|
||||||
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
|
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
|
||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
}
|
}
|
||||||
nudged = false;
|
nudged = false;
|
||||||
if x == -1 {
|
if x == -1 {
|
||||||
points[offset] = 0.0;
|
points[offset].x = 0.0;
|
||||||
nudged = true;
|
nudged = true;
|
||||||
} else if x == width as i32 {
|
} else if x == width as i32 {
|
||||||
points[offset] = width as f32 - 1.0;
|
points[offset].x = width as f32 - 1.0;
|
||||||
nudged = true;
|
nudged = true;
|
||||||
}
|
}
|
||||||
if y == -1 {
|
if y == -1 {
|
||||||
points[offset + 1] = 0.0;
|
points[offset].y = 0.0;
|
||||||
nudged = true;
|
nudged = true;
|
||||||
} else if y == height as i32 {
|
} else if y == height as i32 {
|
||||||
points[offset + 1] = height as f32 - 1.0;
|
points[offset].y = height as f32 - 1.0;
|
||||||
nudged = true;
|
nudged = true;
|
||||||
}
|
}
|
||||||
offset += 2;
|
offset += 1;
|
||||||
}
|
}
|
||||||
// Check and nudge points from end:
|
// Check and nudge points from end:
|
||||||
nudged = true;
|
nudged = true;
|
||||||
let mut offset = points.len() as isize - 2;
|
let mut offset = points.len() as isize - 1;
|
||||||
while offset >= 0 && nudged {
|
while offset >= 0 && nudged {
|
||||||
// for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {
|
// for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {
|
||||||
let x = points[offset as usize] as i32;
|
let x = points[offset as usize].x as i32;
|
||||||
let y = points[offset as usize + 1] as i32;
|
let y = points[offset as usize].y as i32;
|
||||||
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
|
if x < -1 || x > width as i32 || y < -1 || y > height as i32 {
|
||||||
return Err(Exceptions::NOT_FOUND);
|
return Err(Exceptions::NOT_FOUND);
|
||||||
}
|
}
|
||||||
nudged = false;
|
nudged = false;
|
||||||
if x == -1 {
|
if x == -1 {
|
||||||
points[offset as usize] = 0.0;
|
points[offset as usize].x = 0.0;
|
||||||
nudged = true;
|
nudged = true;
|
||||||
} else if x == width as i32 {
|
} 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;
|
nudged = true;
|
||||||
}
|
}
|
||||||
if y == -1 {
|
if y == -1 {
|
||||||
points[offset as usize + 1] = 0.0;
|
points[offset as usize].y = 0.0;
|
||||||
nudged = true;
|
nudged = true;
|
||||||
} else if y == height as i32 {
|
} 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;
|
nudged = true;
|
||||||
}
|
}
|
||||||
offset += -2;
|
offset += -1;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -185,11 +185,15 @@ pub trait GridSampler {
|
|||||||
pub struct SamplerControl {
|
pub struct SamplerControl {
|
||||||
pub p0: Point,
|
pub p0: Point,
|
||||||
pub p1: Point,
|
pub p1: Point,
|
||||||
pub transform: PerspectiveTransform
|
pub transform: PerspectiveTransform,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SamplerControl {
|
impl SamplerControl {
|
||||||
pub fn new( width: u32, height: u32, transform: PerspectiveTransform ) -> Self {
|
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 }
|
Self {
|
||||||
|
p0: point(0.0, 0.0),
|
||||||
|
p1: point(width as f32, height as f32),
|
||||||
|
transform,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
use std::ops::Mul;
|
use std::ops::Mul;
|
||||||
|
|
||||||
use crate::point;
|
use crate::{common::Result, point, Exceptions, Point};
|
||||||
|
|
||||||
use super::Quadrilateral;
|
use super::Quadrilateral;
|
||||||
|
|
||||||
@@ -68,41 +68,27 @@ impl PerspectiveTransform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn quadrilateralToQuadrilateral(
|
pub fn quadrilateralToQuadrilateral(dst: Quadrilateral, src: Quadrilateral) -> Result<Self> {
|
||||||
dst: Quadrilateral,
|
if !src.is_convex() || !dst.is_convex() {
|
||||||
src: Quadrilateral
|
return Err(Exceptions::ILLEGAL_STATE);
|
||||||
) -> Self {
|
}
|
||||||
|
|
||||||
// let q_to_s = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
|
// let q_to_s = PerspectiveTransform::quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||||
// let s_to_q =
|
// let s_to_q =
|
||||||
// PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
|
// PerspectiveTransform::squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
|
||||||
|
|
||||||
let q_to_s = PerspectiveTransform::quadrilateralToSquare(dst);
|
let q_to_s = PerspectiveTransform::quadrilateralToSquare(dst);
|
||||||
let s_to_q =
|
let s_to_q = PerspectiveTransform::squareToQuadrilateral(src);
|
||||||
PerspectiveTransform::squareToQuadrilateral(src);
|
Ok(s_to_q * q_to_s)
|
||||||
s_to_q * q_to_s
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_points_single(&self, points: &mut [f32]) {
|
pub fn transform_points_single(&self, points: &mut [Point]) {
|
||||||
let a11 = self.a11;
|
for point in points.iter_mut() {
|
||||||
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 {
|
|
||||||
// for (int i = 0; i < maxI; i += 2) {
|
// for (int i = 0; i < maxI; i += 2) {
|
||||||
let x = points[i];
|
let x = point.x;
|
||||||
let y = points[i + 1];
|
let y = point.y;
|
||||||
let denominator = a13 * x + a23 * y + a33;
|
let denominator = self.a13 * x + self.a23 * y + self.a33;
|
||||||
points[i] = (a11 * x + a21 * y + a31) / denominator;
|
point.x = (self.a11 * x + self.a21 * y + self.a31) / denominator;
|
||||||
points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
|
point.y = (self.a12 * x + self.a22 * y + self.a32) / denominator;
|
||||||
i += 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,23 +104,30 @@ impl PerspectiveTransform {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn squareToQuadrilateral(
|
pub fn squareToQuadrilateral(square: Quadrilateral) -> Self {
|
||||||
square: Quadrilateral
|
let [p0, p1, p2, p3] = square.0;
|
||||||
) -> 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 {
|
|
||||||
|
|
||||||
let d1 = p1 - p2;
|
let d3 = p0 - p1 + p2 - p3;
|
||||||
let d2 = p3 - p2;
|
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 denominator = d1.cross(d2);
|
||||||
let a13 = (d3.x * d2.y - d2.x * d3.y) / denominator;
|
let a13 = d3.cross(d2) / denominator;
|
||||||
let a23 = (d1.x * d3.y - d3.x * d1.y) / denominator;
|
let a23 = d1.cross(d3) / denominator;
|
||||||
PerspectiveTransform::new(
|
PerspectiveTransform::new(
|
||||||
p1.x - p0.x + a13 * p1.x,
|
p1.x - p0.x + a13 * p1.x,
|
||||||
p3.x - p0.x + a23 * p3.x,
|
p3.x - p0.x + a23 * p3.x,
|
||||||
@@ -150,9 +143,7 @@ let d2 = p3 - p2;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn quadrilateralToSquare(
|
pub fn quadrilateralToSquare(quad: Quadrilateral) -> Self {
|
||||||
quad: Quadrilateral
|
|
||||||
) -> Self {
|
|
||||||
// Here, the adjoint serves as the inverse
|
// Here, the adjoint serves as the inverse
|
||||||
PerspectiveTransform::squareToQuadrilateral(quad).buildAdjoint()
|
PerspectiveTransform::squareToQuadrilateral(quad).buildAdjoint()
|
||||||
}
|
}
|
||||||
@@ -189,4 +180,4 @@ impl Mul for PerspectiveTransform {
|
|||||||
self.a13 * rhs.a31 + self.a23 * rhs.a32 + self.a33 * rhs.a33,
|
self.a13 * rhs.a31 + self.a23 * rhs.a32 + self.a33 * rhs.a33,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ impl Quadrilateral {
|
|||||||
// using Point = T;
|
// using Point = T;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn new(tl:Point, tr: Point, br: Point, bl: Point) -> Self {
|
pub fn new(tl: Point, tr: Point, br: Point, bl: Point) -> Self {
|
||||||
Self([tl,tr,br,bl])
|
Self([tl, tr, br, bl])
|
||||||
}
|
}
|
||||||
// pub fn with_f32( tl:f32, tr:f32, br:f32, bl:f32) -> Self {
|
// pub fn with_f32( tl:f32, tr:f32, br:f32, bl:f32) -> Self {
|
||||||
// Self([tl, tr,br, bl ])
|
// Self([tl, tr,br, bl ])
|
||||||
@@ -124,11 +124,11 @@ impl Quadrilateral {
|
|||||||
let d2 = self.0[i] - self.0[(i + 1) % N];
|
let d2 = self.0[i] - self.0[(i + 1) % N];
|
||||||
let cp = d1.cross(d2);
|
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 = if M.abs() > cp { M.abs() } else { cp };
|
||||||
// m = std::cmp::min((m).abs(), cp);
|
m = f32::min((m).abs(), cp);
|
||||||
// M = std::cmp::max((M).abs(), cp);
|
M = f32::max((M).abs(), cp);
|
||||||
|
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
sign = cp > 0.0;
|
sign = cp > 0.0;
|
||||||
@@ -214,4 +214,4 @@ impl Default for Quadrilateral {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self([Point { x: 0.0, y: 0.0 }; 4])
|
Self([Point { x: 0.0, y: 0.0 }; 4])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{
|
common::{
|
||||||
detector::WhiteRectangleDetector, BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral,
|
detector::WhiteRectangleDetector, BitMatrix, DefaultGridSampler, GridSampler,
|
||||||
|
Quadrilateral, Result,
|
||||||
},
|
},
|
||||||
point, Exceptions, Point,
|
point, Exceptions, Point,
|
||||||
};
|
};
|
||||||
@@ -334,15 +335,15 @@ impl<'a> Detector<'_> {
|
|||||||
) -> Result<BitMatrix> {
|
) -> Result<BitMatrix> {
|
||||||
let sampler = DefaultGridSampler::default();
|
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 dst = Quadrilateral::new(
|
||||||
let src = Quadrilateral::new(topRight, topLeft,bottomRight, bottomLeft);
|
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(
|
sampler.sample_grid_detailed(image, dimensionX, dimensionY, dst, src)
|
||||||
image,
|
|
||||||
dimensionX,
|
|
||||||
dimensionY,
|
|
||||||
dst, src
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,13 +14,14 @@ macro_rules! CHECK {
|
|||||||
use std::{cell::RefCell, rc::Rc};
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitMatrix, DefaultGridSampler, GridSampler, Result, Quadrilateral},
|
common::{BitMatrix, DefaultGridSampler, GridSampler, Quadrilateral, Result},
|
||||||
datamatrix::detector::{
|
datamatrix::detector::{
|
||||||
zxing_cpp_detector::{util::intersect, BitMatrixCursor, RegressionLine},
|
zxing_cpp_detector::{util::intersect, BitMatrixCursor, RegressionLine},
|
||||||
DatamatrixDetectorResult,
|
DatamatrixDetectorResult,
|
||||||
},
|
},
|
||||||
|
point,
|
||||||
qrcode::encoder::ByteMatrix,
|
qrcode::encoder::ByteMatrix,
|
||||||
Exceptions, Point, point,
|
Exceptions, Point,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{DMRegressionLine, EdgeTracer};
|
use super::{DMRegressionLine, EdgeTracer};
|
||||||
@@ -212,15 +213,16 @@ fn Scan(
|
|||||||
|
|
||||||
let grid_sampler = DefaultGridSampler::default();
|
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 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 dst = Quadrilateral::new(
|
||||||
let src = sourcePoints;
|
point(0.0, 0.0),
|
||||||
|
point(dimT as f32, 0.0),
|
||||||
let res = grid_sampler.sample_grid_detailed(
|
point(dimT as f32, dimR as f32),
|
||||||
startTracer.img,
|
point(0.0, dimR as f32),
|
||||||
dimT as u32,
|
|
||||||
dimR as u32,
|
|
||||||
dst, src
|
|
||||||
);
|
);
|
||||||
|
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);
|
// let res = grid_sampler.sample_grid(startTracer.img, dimT as u32, dimR as u32, &transform);
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
use num::integer::Roots;
|
use num::integer::Roots;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler, Result, Quadrilateral},
|
common::{
|
||||||
|
BitMatrix, DefaultGridSampler, DetectorRXingResult, GridSampler, Quadrilateral, Result,
|
||||||
|
},
|
||||||
point, Exceptions, Point,
|
point, Exceptions, Point,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -346,9 +348,12 @@ pub fn detect(image: &BitMatrix, try_harder: bool) -> Result<MaxicodeDetectionRe
|
|||||||
// let target_width = (tr.0 - tl.0).round().abs() as u32;
|
// let target_width = (tr.0 - tl.0).round().abs() as u32;
|
||||||
// let target_height = (br.1 - tr.1).round().abs() as u32;
|
// let target_height = (br.1 - tr.1).round().abs() as u32;
|
||||||
|
|
||||||
let dst = Quadrilateral::new(point(0.0,0.0), point(target_width,0.0), point(target_width,
|
let dst = Quadrilateral::new(
|
||||||
target_height), point(0.0,
|
point(0.0, 0.0),
|
||||||
target_height));
|
point(target_width, 0.0),
|
||||||
|
point(target_width, target_height),
|
||||||
|
point(0.0, target_height),
|
||||||
|
);
|
||||||
let src = Quadrilateral::new(tl, tr, br, bl);
|
let src = Quadrilateral::new(tl, tr, br, bl);
|
||||||
|
|
||||||
let Ok(bits) = grid_sampler.sample_grid_detailed(
|
let Ok(bits) = grid_sampler.sample_grid_detailed(
|
||||||
|
|||||||
@@ -17,7 +17,10 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::{BitMatrix, DefaultGridSampler, GridSampler, PerspectiveTransform, Result, Quadrilateral, SamplerControl},
|
common::{
|
||||||
|
BitMatrix, DefaultGridSampler, GridSampler, PerspectiveTransform, Quadrilateral, Result,
|
||||||
|
SamplerControl,
|
||||||
|
},
|
||||||
point,
|
point,
|
||||||
qrcode::decoder::Version,
|
qrcode::decoder::Version,
|
||||||
DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, Point, PointCallback,
|
DecodeHintType, DecodeHintValue, DecodingHintDictionary, Exceptions, Point, PointCallback,
|
||||||
@@ -193,16 +196,20 @@ impl<'a> Detector<'_> {
|
|||||||
sourceBottomRightY = dimMinusThree;
|
sourceBottomRightY = dimMinusThree;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dst = Quadrilateral::new(point(3.5,
|
let dst = Quadrilateral::new(
|
||||||
3.5), point(dimMinusThree,
|
point(3.5, 3.5),
|
||||||
3.5), point(sourceBottomRightX,
|
point(dimMinusThree, 3.5),
|
||||||
sourceBottomRightY), point(3.5,
|
point(sourceBottomRightX, sourceBottomRightY),
|
||||||
dimMinusThree));
|
point(3.5, dimMinusThree),
|
||||||
let src = Quadrilateral::new( topLeft, topRight, point(bottomRightX, bottomRightY), bottomLeft);
|
);
|
||||||
|
let src = Quadrilateral::new(
|
||||||
|
topLeft,
|
||||||
|
topRight,
|
||||||
|
point(bottomRightX, bottomRightY),
|
||||||
|
bottomLeft,
|
||||||
|
);
|
||||||
|
|
||||||
Some(PerspectiveTransform::quadrilateralToQuadrilateral(
|
PerspectiveTransform::quadrilateralToQuadrilateral(dst, src).ok()
|
||||||
dst, src
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sampleGrid(
|
fn sampleGrid(
|
||||||
@@ -211,7 +218,12 @@ impl<'a> Detector<'_> {
|
|||||||
dimension: u32,
|
dimension: u32,
|
||||||
) -> Result<BitMatrix> {
|
) -> Result<BitMatrix> {
|
||||||
let sampler = DefaultGridSampler::default();
|
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)],
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user