mirror of
https://github.com/starovoid/rxing.git
synced 2026-07-26 04:12:34 +00:00
port: rMQR: improve detection rate by using finder sub pattern
677fc21c7d
This commit is contained in:
@@ -1232,6 +1232,124 @@ pub fn SampleRMQR(image: &BitMatrix, fp: ConcentricPattern) -> Result<QRCodeDete
|
|||||||
|
|
||||||
let dim = Version::SymbolSize(bestFI.microVersion, Type::RectMicro);
|
let dim = Version::SymbolSize(bestFI.microVersion, Type::RectMicro);
|
||||||
|
|
||||||
|
// TODO: this is a WIP
|
||||||
|
let intersectQuads = |a: &Quadrilateral, b: &Quadrilateral| -> Result<Quadrilateral> {
|
||||||
|
let tl = a.center();
|
||||||
|
let br = b.center();
|
||||||
|
// rotate points such that topLeft of a is furthest away from b and topLeft of b is closest to a
|
||||||
|
// let dist2B = /*[c = br]*/| &a, &b| { Some(Point::distance(a, br).partial_cmp(&Point::distance(b, br))) };
|
||||||
|
|
||||||
|
let offsetATarget =
|
||||||
|
a.0.iter()
|
||||||
|
.max_by(|a, b| {
|
||||||
|
Point::distance(**a, br)
|
||||||
|
.partial_cmp(&Point::distance(**b, br))
|
||||||
|
.unwrap_or(std::cmp::Ordering::Less)
|
||||||
|
})
|
||||||
|
.ok_or(Exceptions::FORMAT)?;
|
||||||
|
let offsetA =
|
||||||
|
a.0.iter()
|
||||||
|
.position(|x| x == offsetATarget)
|
||||||
|
.ok_or(Exceptions::FORMAT)? as i32;
|
||||||
|
// let offsetA = std::max_element(a.begin(), a.end(), dist2B) - a.begin();
|
||||||
|
// let dist2A = /*[c = tl]*/| a, b| { Point::distance(a, tl) < Point::distance(b, tl) };
|
||||||
|
let offsetBTarget =
|
||||||
|
b.0.iter()
|
||||||
|
.min_by(|a, b| {
|
||||||
|
Point::distance(**a, tl)
|
||||||
|
.partial_cmp(&Point::distance(**b, tl))
|
||||||
|
.unwrap_or(std::cmp::Ordering::Less)
|
||||||
|
})
|
||||||
|
.ok_or(Exceptions::FORMAT)?;
|
||||||
|
let offsetB =
|
||||||
|
b.0.iter()
|
||||||
|
.position(|x| x == offsetBTarget)
|
||||||
|
.ok_or(Exceptions::FORMAT)? as i32;
|
||||||
|
// let offsetB = std::min_element(b.begin(), b.end(), dist2A) - b.begin();
|
||||||
|
|
||||||
|
let a = a.rotated_corners(Some(offsetA), None);
|
||||||
|
let b = b.rotated_corners(Some(offsetB), None);
|
||||||
|
// a = RotatedCorners(a, offsetA);
|
||||||
|
// b = RotatedCorners(b, offsetB);
|
||||||
|
let tr = (RegressionLine::intersect(
|
||||||
|
&RegressionLine::with_two_points(a[0], a[1]),
|
||||||
|
&RegressionLine::with_two_points(b[1], b[2]),
|
||||||
|
)
|
||||||
|
.ok_or(Exceptions::FORMAT)?
|
||||||
|
+ RegressionLine::intersect(
|
||||||
|
&RegressionLine::with_two_points(a[3], a[2]),
|
||||||
|
&RegressionLine::with_two_points(b[0], b[3]),
|
||||||
|
)
|
||||||
|
.ok_or(Exceptions::FORMAT)?)
|
||||||
|
/ 2.0;
|
||||||
|
|
||||||
|
// let tr = (intersect(RegressionLine(a[0], a[1]), RegressionLine(b[1], b[2]))
|
||||||
|
// + intersect(RegressionLine(a[3], a[2]), RegressionLine(b[0], b[3])))
|
||||||
|
// / 2;
|
||||||
|
let bl = (RegressionLine::intersect(
|
||||||
|
&RegressionLine::with_two_points(a[0], a[3]),
|
||||||
|
&RegressionLine::with_two_points(b[2], b[3]),
|
||||||
|
)
|
||||||
|
.ok_or(Exceptions::FORMAT)?
|
||||||
|
+ RegressionLine::intersect(
|
||||||
|
&RegressionLine::with_two_points(a[1], a[2]),
|
||||||
|
&RegressionLine::with_two_points(b[0], b[1]),
|
||||||
|
)
|
||||||
|
.ok_or(Exceptions::FORMAT)?)
|
||||||
|
/ 2.0;
|
||||||
|
// let bl = (intersect(RegressionLine(a[0], a[3]), RegressionLine(b[2], b[3]))
|
||||||
|
// + intersect(RegressionLine(a[1], a[2]), RegressionLine(b[0], b[1])))
|
||||||
|
// / 2;
|
||||||
|
|
||||||
|
// log(tr, 2);
|
||||||
|
// log(bl, 2);
|
||||||
|
|
||||||
|
Ok(Quadrilateral::from([tl, tr, br, bl]))
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(found) = LocateAlignmentPattern(
|
||||||
|
image,
|
||||||
|
fp.size / 7,
|
||||||
|
bestPT.transform_point(Into::<Point>::into(dim) - point_f(3.0, 3.0)),
|
||||||
|
) {
|
||||||
|
// if ( found ) {
|
||||||
|
// log(*found, 2);
|
||||||
|
if let Some(spQuad) = FindConcentricPatternCorners(image, found, fp.size / 2, 1) {
|
||||||
|
// if (auto spQuad = FindConcentricPatternCorners(image, *found, fp.size / 2, 1)) {
|
||||||
|
let mut dest = intersectQuads(&fpQuad, &spQuad)?;
|
||||||
|
if (dim.y <= 9) {
|
||||||
|
bestPT = PerspectiveTransform::quadrilateralToQuadrilateral(
|
||||||
|
Quadrilateral::from([
|
||||||
|
point(6.5, 0.5),
|
||||||
|
point(dim.x as f32 - 1.5, dim.y as f32 - 3.5),
|
||||||
|
point(dim.x as f32 - 1.5, dim.y as f32 - 1.5),
|
||||||
|
point(6.5, 6.5),
|
||||||
|
]),
|
||||||
|
Quadrilateral::from([
|
||||||
|
*fpQuad.top_right(),
|
||||||
|
*spQuad.top_right(),
|
||||||
|
*spQuad.bottom_right(),
|
||||||
|
*fpQuad.bottom_right(),
|
||||||
|
]),
|
||||||
|
)?;
|
||||||
|
// bestPT = PerspectiveTransform({{6.5, 0.5}, {dim.x - 1.5, dim.y - 3.5}, {dim.x - 1.5, dim.y - 1.5}, {6.5, 6.5}},
|
||||||
|
// {fpQuad->topRight(), spQuad->topRight(), spQuad->bottomRight(), fpQuad->bottomRight()});
|
||||||
|
} else {
|
||||||
|
dest[0] = fp.p;
|
||||||
|
dest[2] = found;
|
||||||
|
bestPT = PerspectiveTransform::quadrilateralToQuadrilateral(
|
||||||
|
Quadrilateral::from([
|
||||||
|
point(3.5, 3.5),
|
||||||
|
point(dim.x as f32 - 2.5, 3.5),
|
||||||
|
point(dim.x as f32 - 2.5, dim.y as f32 - 2.5),
|
||||||
|
point(3.5, dim.y as f32 - 2.5),
|
||||||
|
]),
|
||||||
|
dest,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let grid_sampler = DefaultGridSampler;
|
let grid_sampler = DefaultGridSampler;
|
||||||
let (sample, rps) = grid_sampler.sample_grid(
|
let (sample, rps) = grid_sampler.sample_grid(
|
||||||
image,
|
image,
|
||||||
|
|||||||
@@ -309,15 +309,6 @@ impl<T: Reader> AbstractBlackBoxTestCase<T> {
|
|||||||
log::fine(format!("could not read at rotation {rotation} w/TH: {e:?}"));
|
log::fine(format!("could not read at rotation {rotation} w/TH: {e:?}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// try {
|
|
||||||
// if (decode(bitmap, rotation, expectedText, expectedMetadata, true)) {
|
|
||||||
// tryHarderCounts[x]+=1;
|
|
||||||
// } else {
|
|
||||||
// tryHarderMisreadCounts[x]+=1;
|
|
||||||
// }
|
|
||||||
// } catch (ReaderException ignored) {
|
|
||||||
// log::fine(format!("could not read at rotation {} w/TH", rotation));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use rxing::{qrcode::cpp_port::QrReader, BarcodeFormat, MultiUseMultiFormatReader};
|
use rxing::{
|
||||||
|
qrcode::cpp_port::QrReader, BarcodeFormat, MultiFormatReader, MultiUseMultiFormatReader,
|
||||||
|
};
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
|
||||||
@@ -316,13 +318,19 @@ fn cpp_qrcode_black_box7_test_case() {
|
|||||||
fn cpp_rmqr_blackbox_test_case() {
|
fn cpp_rmqr_blackbox_test_case() {
|
||||||
let mut tester = common::AbstractBlackBoxTestCase::new(
|
let mut tester = common::AbstractBlackBoxTestCase::new(
|
||||||
"test_resources/blackbox/cpp/rmqrcode-1",
|
"test_resources/blackbox/cpp/rmqrcode-1",
|
||||||
QrReader,
|
MultiFormatReader::default(),
|
||||||
BarcodeFormat::RECTANGULAR_MICRO_QR_CODE,
|
BarcodeFormat::RECTANGULAR_MICRO_QR_CODE,
|
||||||
);
|
);
|
||||||
tester.add_test(2, 2, 0.0);
|
// tester.ignore_pure = true;
|
||||||
tester.add_test(1, 1, 90.0);
|
tester.add_test(3, 3, 0.0);
|
||||||
tester.add_test(1, 1, 180.0);
|
tester.add_test(3, 3, 90.0);
|
||||||
tester.add_test(1, 1, 270.0);
|
tester.add_test(3, 3, 180.0);
|
||||||
|
tester.add_test(3, 3, 270.0);
|
||||||
|
|
||||||
|
tester.add_hint(
|
||||||
|
rxing::DecodeHintType::ALSO_INVERTED,
|
||||||
|
rxing::DecodeHintValue::AlsoInverted(true),
|
||||||
|
);
|
||||||
|
|
||||||
tester.test_black_box();
|
tester.test_black_box();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user