mirror of
https://github.com/zxing/zxing.git
synced 2025-02-02 05:41:08 -08:00
Opening up the Detector a little to allow extension, such as per Ralf
git-svn-id: https://zxing.googlecode.com/svn/trunk@1143 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
27be3fb930
commit
9f3ee05fe1
|
@ -38,6 +38,12 @@ public final class DefaultGridSampler extends GridSampler {
|
|||
p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY,
|
||||
p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);
|
||||
|
||||
return sampleGrid(image, dimension, transform);
|
||||
}
|
||||
|
||||
public BitMatrix sampleGrid(BitMatrix image,
|
||||
int dimension,
|
||||
PerspectiveTransform transform) throws ReaderException {
|
||||
BitMatrix bits = new BitMatrix(dimension);
|
||||
float[] points = new float[dimension << 1];
|
||||
for (int y = 0; y < dimension; y++) {
|
||||
|
|
|
@ -92,6 +92,13 @@ public abstract class GridSampler {
|
|||
float p3FromX, float p3FromY,
|
||||
float p4FromX, float p4FromY) throws ReaderException;
|
||||
|
||||
public BitMatrix sampleGrid(BitMatrix image,
|
||||
int dimension,
|
||||
PerspectiveTransform transform) throws ReaderException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Checks a set of points that have been transformed to sample points on an image against
|
||||
* the image's dimensions to see if the point are even within the image.</p>
|
||||
|
|
|
@ -23,7 +23,7 @@ package com.google.zxing.common;
|
|||
*
|
||||
* @author Sean Owen
|
||||
*/
|
||||
final class PerspectiveTransform {
|
||||
public final class PerspectiveTransform {
|
||||
|
||||
private final float a11, a12, a13, a21, a22, a23, a31, a32, a33;
|
||||
|
||||
|
@ -41,21 +41,21 @@ final class PerspectiveTransform {
|
|||
this.a33 = a33;
|
||||
}
|
||||
|
||||
static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3,
|
||||
float x0p, float y0p,
|
||||
float x1p, float y1p,
|
||||
float x2p, float y2p,
|
||||
float x3p, float y3p) {
|
||||
public static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3,
|
||||
float x0p, float y0p,
|
||||
float x1p, float y1p,
|
||||
float x2p, float y2p,
|
||||
float x3p, float y3p) {
|
||||
|
||||
PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||
PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
|
||||
return sToQ.times(qToS);
|
||||
}
|
||||
|
||||
void transformPoints(float[] points) {
|
||||
public void transformPoints(float[] points) {
|
||||
int max = points.length;
|
||||
float a11 = this.a11;
|
||||
float a12 = this.a12;
|
||||
|
@ -75,10 +75,22 @@ final class PerspectiveTransform {
|
|||
}
|
||||
}
|
||||
|
||||
static PerspectiveTransform squareToQuadrilateral(float x0, float y0,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3) {
|
||||
/** Convenience method, not optimized for performance. */
|
||||
public void transformPoints(float[] xValues, float[] yValues) {
|
||||
int n = xValues.length;
|
||||
for (int i = 0; i < n; i ++) {
|
||||
float x = xValues[i];
|
||||
float y = yValues[i];
|
||||
float denominator = a13 * x + a23 * y + a33;
|
||||
xValues[i] = (a11 * x + a21 * y + a31) / denominator;
|
||||
yValues[i] = (a12 * x + a22 * y + a32) / denominator;
|
||||
}
|
||||
}
|
||||
|
||||
public static PerspectiveTransform squareToQuadrilateral(float x0, float y0,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3) {
|
||||
float dy2 = y3 - y2;
|
||||
float dy3 = y0 - y1 + y2 - y3;
|
||||
if (dy2 == 0.0f && dy3 == 0.0f) {
|
||||
|
@ -99,10 +111,10 @@ final class PerspectiveTransform {
|
|||
}
|
||||
}
|
||||
|
||||
private static PerspectiveTransform quadrilateralToSquare(float x0, float y0,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3) {
|
||||
public static PerspectiveTransform quadrilateralToSquare(float x0, float y0,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
float x3, float y3) {
|
||||
// Here, the adjoint serves as the inverse:
|
||||
return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import com.google.zxing.ResultPointCallback;
|
|||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.common.DetectorResult;
|
||||
import com.google.zxing.common.GridSampler;
|
||||
import com.google.zxing.common.PerspectiveTransform;
|
||||
import com.google.zxing.qrcode.decoder.Version;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
@ -46,6 +47,10 @@ public class Detector {
|
|||
return image;
|
||||
}
|
||||
|
||||
protected ResultPointCallback getResultPointCallback() {
|
||||
return resultPointCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Detects a QR Code in an image, simply.</p>
|
||||
*
|
||||
|
@ -117,7 +122,10 @@ public class Detector {
|
|||
// If we didn't find alignment pattern... well try anyway without it
|
||||
}
|
||||
|
||||
BitMatrix bits = sampleGrid(image, topLeft, topRight, bottomLeft, alignmentPattern, dimension);
|
||||
PerspectiveTransform transform =
|
||||
createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
|
||||
|
||||
BitMatrix bits = sampleGrid(image, transform, dimension);
|
||||
|
||||
ResultPoint[] points;
|
||||
if (alignmentPattern == null) {
|
||||
|
@ -128,12 +136,11 @@ public class Detector {
|
|||
return new DetectorResult(bits, points);
|
||||
}
|
||||
|
||||
private static BitMatrix sampleGrid(BitMatrix image,
|
||||
ResultPoint topLeft,
|
||||
ResultPoint topRight,
|
||||
ResultPoint bottomLeft,
|
||||
ResultPoint alignmentPattern,
|
||||
int dimension) throws ReaderException {
|
||||
public PerspectiveTransform createTransform(ResultPoint topLeft,
|
||||
ResultPoint topRight,
|
||||
ResultPoint bottomLeft,
|
||||
ResultPoint alignmentPattern,
|
||||
int dimension) {
|
||||
float dimMinusThree = (float) dimension - 3.5f;
|
||||
float bottomRightX;
|
||||
float bottomRightY;
|
||||
|
@ -150,10 +157,7 @@ public class Detector {
|
|||
sourceBottomRightX = sourceBottomRightY = dimMinusThree;
|
||||
}
|
||||
|
||||
GridSampler sampler = GridSampler.getInstance();
|
||||
return sampler.sampleGrid(
|
||||
image,
|
||||
dimension,
|
||||
PerspectiveTransform transform = PerspectiveTransform.quadrilateralToQuadrilateral(
|
||||
3.5f,
|
||||
3.5f,
|
||||
dimMinusThree,
|
||||
|
@ -170,15 +174,25 @@ public class Detector {
|
|||
bottomRightY,
|
||||
bottomLeft.getX(),
|
||||
bottomLeft.getY());
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
private static BitMatrix sampleGrid(BitMatrix image,
|
||||
PerspectiveTransform transform,
|
||||
int dimension) throws ReaderException {
|
||||
|
||||
GridSampler sampler = GridSampler.getInstance();
|
||||
return sampler.sampleGrid(image, dimension, transform);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
|
||||
* of the finder patterns and estimated module size.</p>
|
||||
*/
|
||||
private static int computeDimension(ResultPoint topLeft,
|
||||
ResultPoint topRight,
|
||||
ResultPoint bottomLeft,
|
||||
protected static int computeDimension(ResultPoint topLeft,
|
||||
ResultPoint topRight,
|
||||
ResultPoint bottomLeft,
|
||||
float moduleSize) throws ReaderException {
|
||||
int tltrCentersDimension = round(ResultPoint.distance(topLeft, topRight) / moduleSize);
|
||||
int tlblCentersDimension = round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
|
||||
|
@ -201,8 +215,9 @@ public class Detector {
|
|||
* <p>Computes an average estimated module size based on estimated derived from the positions
|
||||
* of the three finder patterns.</p>
|
||||
*/
|
||||
private float calculateModuleSize(ResultPoint topLeft, ResultPoint topRight,
|
||||
ResultPoint bottomLeft) {
|
||||
protected float calculateModuleSize(ResultPoint topLeft,
|
||||
ResultPoint topRight,
|
||||
ResultPoint bottomLeft) {
|
||||
// Take the average
|
||||
return (calculateModuleSizeOneWay(topLeft, topRight) +
|
||||
calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
|
||||
|
@ -329,10 +344,10 @@ public class Detector {
|
|||
* @return {@link AlignmentPattern} if found, or null otherwise
|
||||
* @throws ReaderException if an unexpected error occurs during detection
|
||||
*/
|
||||
private AlignmentPattern findAlignmentInRegion(float overallEstModuleSize,
|
||||
int estAlignmentX,
|
||||
int estAlignmentY,
|
||||
float allowanceFactor)
|
||||
protected AlignmentPattern findAlignmentInRegion(float overallEstModuleSize,
|
||||
int estAlignmentX,
|
||||
int estAlignmentY,
|
||||
float allowanceFactor)
|
||||
throws ReaderException {
|
||||
// Look for an alignment pattern (3 modules in size) around where it
|
||||
// should be
|
||||
|
@ -365,5 +380,4 @@ public class Detector {
|
|||
private static int round(float d) {
|
||||
return (int) (d + 0.5f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue