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:
srowen 2009-12-08 19:58:01 +00:00
parent 27be3fb930
commit 9f3ee05fe1
4 changed files with 79 additions and 40 deletions

View file

@ -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++) {

View file

@ -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>

View file

@ -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();
}

View file

@ -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);
}
}