mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -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
core/src/com/google/zxing
|
@ -38,6 +38,12 @@ public final class DefaultGridSampler extends GridSampler {
|
||||||
p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY,
|
p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY,
|
||||||
p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);
|
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);
|
BitMatrix bits = new BitMatrix(dimension);
|
||||||
float[] points = new float[dimension << 1];
|
float[] points = new float[dimension << 1];
|
||||||
for (int y = 0; y < dimension; y++) {
|
for (int y = 0; y < dimension; y++) {
|
||||||
|
|
|
@ -92,6 +92,13 @@ public abstract class GridSampler {
|
||||||
float p3FromX, float p3FromY,
|
float p3FromX, float p3FromY,
|
||||||
float p4FromX, float p4FromY) throws ReaderException;
|
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
|
* <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>
|
* 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
|
* @author Sean Owen
|
||||||
*/
|
*/
|
||||||
final class PerspectiveTransform {
|
public final class PerspectiveTransform {
|
||||||
|
|
||||||
private final float a11, a12, a13, a21, a22, a23, a31, a32, a33;
|
private final float a11, a12, a13, a21, a22, a23, a31, a32, a33;
|
||||||
|
|
||||||
|
@ -41,21 +41,21 @@ final class PerspectiveTransform {
|
||||||
this.a33 = a33;
|
this.a33 = a33;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0,
|
public static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0,
|
||||||
float x1, float y1,
|
float x1, float y1,
|
||||||
float x2, float y2,
|
float x2, float y2,
|
||||||
float x3, float y3,
|
float x3, float y3,
|
||||||
float x0p, float y0p,
|
float x0p, float y0p,
|
||||||
float x1p, float y1p,
|
float x1p, float y1p,
|
||||||
float x2p, float y2p,
|
float x2p, float y2p,
|
||||||
float x3p, float y3p) {
|
float x3p, float y3p) {
|
||||||
|
|
||||||
PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
|
PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
|
||||||
PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
|
PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
|
||||||
return sToQ.times(qToS);
|
return sToQ.times(qToS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void transformPoints(float[] points) {
|
public void transformPoints(float[] points) {
|
||||||
int max = points.length;
|
int max = points.length;
|
||||||
float a11 = this.a11;
|
float a11 = this.a11;
|
||||||
float a12 = this.a12;
|
float a12 = this.a12;
|
||||||
|
@ -75,10 +75,22 @@ final class PerspectiveTransform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static PerspectiveTransform squareToQuadrilateral(float x0, float y0,
|
/** Convenience method, not optimized for performance. */
|
||||||
float x1, float y1,
|
public void transformPoints(float[] xValues, float[] yValues) {
|
||||||
float x2, float y2,
|
int n = xValues.length;
|
||||||
float x3, float y3) {
|
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 dy2 = y3 - y2;
|
||||||
float dy3 = y0 - y1 + y2 - y3;
|
float dy3 = y0 - y1 + y2 - y3;
|
||||||
if (dy2 == 0.0f && dy3 == 0.0f) {
|
if (dy2 == 0.0f && dy3 == 0.0f) {
|
||||||
|
@ -99,10 +111,10 @@ final class PerspectiveTransform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PerspectiveTransform quadrilateralToSquare(float x0, float y0,
|
public static PerspectiveTransform quadrilateralToSquare(float x0, float y0,
|
||||||
float x1, float y1,
|
float x1, float y1,
|
||||||
float x2, float y2,
|
float x2, float y2,
|
||||||
float x3, float y3) {
|
float x3, float y3) {
|
||||||
// Here, the adjoint serves as the inverse:
|
// Here, the adjoint serves as the inverse:
|
||||||
return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();
|
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.BitMatrix;
|
||||||
import com.google.zxing.common.DetectorResult;
|
import com.google.zxing.common.DetectorResult;
|
||||||
import com.google.zxing.common.GridSampler;
|
import com.google.zxing.common.GridSampler;
|
||||||
|
import com.google.zxing.common.PerspectiveTransform;
|
||||||
import com.google.zxing.qrcode.decoder.Version;
|
import com.google.zxing.qrcode.decoder.Version;
|
||||||
|
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
|
@ -46,6 +47,10 @@ public class Detector {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ResultPointCallback getResultPointCallback() {
|
||||||
|
return resultPointCallback;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Detects a QR Code in an image, simply.</p>
|
* <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
|
// 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;
|
ResultPoint[] points;
|
||||||
if (alignmentPattern == null) {
|
if (alignmentPattern == null) {
|
||||||
|
@ -128,12 +136,11 @@ public class Detector {
|
||||||
return new DetectorResult(bits, points);
|
return new DetectorResult(bits, points);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BitMatrix sampleGrid(BitMatrix image,
|
public PerspectiveTransform createTransform(ResultPoint topLeft,
|
||||||
ResultPoint topLeft,
|
ResultPoint topRight,
|
||||||
ResultPoint topRight,
|
ResultPoint bottomLeft,
|
||||||
ResultPoint bottomLeft,
|
ResultPoint alignmentPattern,
|
||||||
ResultPoint alignmentPattern,
|
int dimension) {
|
||||||
int dimension) throws ReaderException {
|
|
||||||
float dimMinusThree = (float) dimension - 3.5f;
|
float dimMinusThree = (float) dimension - 3.5f;
|
||||||
float bottomRightX;
|
float bottomRightX;
|
||||||
float bottomRightY;
|
float bottomRightY;
|
||||||
|
@ -150,10 +157,7 @@ public class Detector {
|
||||||
sourceBottomRightX = sourceBottomRightY = dimMinusThree;
|
sourceBottomRightX = sourceBottomRightY = dimMinusThree;
|
||||||
}
|
}
|
||||||
|
|
||||||
GridSampler sampler = GridSampler.getInstance();
|
PerspectiveTransform transform = PerspectiveTransform.quadrilateralToQuadrilateral(
|
||||||
return sampler.sampleGrid(
|
|
||||||
image,
|
|
||||||
dimension,
|
|
||||||
3.5f,
|
3.5f,
|
||||||
3.5f,
|
3.5f,
|
||||||
dimMinusThree,
|
dimMinusThree,
|
||||||
|
@ -170,15 +174,25 @@ public class Detector {
|
||||||
bottomRightY,
|
bottomRightY,
|
||||||
bottomLeft.getX(),
|
bottomLeft.getX(),
|
||||||
bottomLeft.getY());
|
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
|
* <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>
|
* of the finder patterns and estimated module size.</p>
|
||||||
*/
|
*/
|
||||||
private static int computeDimension(ResultPoint topLeft,
|
protected static int computeDimension(ResultPoint topLeft,
|
||||||
ResultPoint topRight,
|
ResultPoint topRight,
|
||||||
ResultPoint bottomLeft,
|
ResultPoint bottomLeft,
|
||||||
float moduleSize) throws ReaderException {
|
float moduleSize) throws ReaderException {
|
||||||
int tltrCentersDimension = round(ResultPoint.distance(topLeft, topRight) / moduleSize);
|
int tltrCentersDimension = round(ResultPoint.distance(topLeft, topRight) / moduleSize);
|
||||||
int tlblCentersDimension = round(ResultPoint.distance(topLeft, bottomLeft) / 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
|
* <p>Computes an average estimated module size based on estimated derived from the positions
|
||||||
* of the three finder patterns.</p>
|
* of the three finder patterns.</p>
|
||||||
*/
|
*/
|
||||||
private float calculateModuleSize(ResultPoint topLeft, ResultPoint topRight,
|
protected float calculateModuleSize(ResultPoint topLeft,
|
||||||
ResultPoint bottomLeft) {
|
ResultPoint topRight,
|
||||||
|
ResultPoint bottomLeft) {
|
||||||
// Take the average
|
// Take the average
|
||||||
return (calculateModuleSizeOneWay(topLeft, topRight) +
|
return (calculateModuleSizeOneWay(topLeft, topRight) +
|
||||||
calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
|
calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
|
||||||
|
@ -329,10 +344,10 @@ public class Detector {
|
||||||
* @return {@link AlignmentPattern} if found, or null otherwise
|
* @return {@link AlignmentPattern} if found, or null otherwise
|
||||||
* @throws ReaderException if an unexpected error occurs during detection
|
* @throws ReaderException if an unexpected error occurs during detection
|
||||||
*/
|
*/
|
||||||
private AlignmentPattern findAlignmentInRegion(float overallEstModuleSize,
|
protected AlignmentPattern findAlignmentInRegion(float overallEstModuleSize,
|
||||||
int estAlignmentX,
|
int estAlignmentX,
|
||||||
int estAlignmentY,
|
int estAlignmentY,
|
||||||
float allowanceFactor)
|
float allowanceFactor)
|
||||||
throws ReaderException {
|
throws ReaderException {
|
||||||
// Look for an alignment pattern (3 modules in size) around where it
|
// Look for an alignment pattern (3 modules in size) around where it
|
||||||
// should be
|
// should be
|
||||||
|
@ -365,5 +380,4 @@ public class Detector {
|
||||||
private static int round(float d) {
|
private static int round(float d) {
|
||||||
return (int) (d + 0.5f);
|
return (int) (d + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue