X-Git-Url: http://git.rot13.org/?p=zxing.git;a=blobdiff_plain;f=core%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fdatamatrix%2Fdetector%2FDetector.java;h=206e5187c36ade495c10144926246d850dc8e3b0;hp=eed0dfd65d800ccfad45a0b90ca11265d7298eab;hb=18e3e8522fb403891dc211e6de9681dcf1030b66;hpb=85e4e130a34fcf20b28cbdf11b4b78c9bda02bc7 diff --git a/core/src/com/google/zxing/datamatrix/detector/Detector.java b/core/src/com/google/zxing/datamatrix/detector/Detector.java index eed0dfd6..206e5187 100644 --- a/core/src/com/google/zxing/datamatrix/detector/Detector.java +++ b/core/src/com/google/zxing/datamatrix/detector/Detector.java @@ -16,15 +16,14 @@ package com.google.zxing.datamatrix.detector; -import com.google.zxing.MonochromeBitmapSource; -import com.google.zxing.ReaderException; +import com.google.zxing.NotFoundException; import com.google.zxing.ResultPoint; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.Collections; import com.google.zxing.common.Comparator; import com.google.zxing.common.DetectorResult; import com.google.zxing.common.GridSampler; -import com.google.zxing.common.detector.MonochromeRectangleDetector; +import com.google.zxing.common.detector.WhiteRectangleDetector; import java.util.Enumeration; import java.util.Hashtable; @@ -38,28 +37,27 @@ import java.util.Vector; */ public final class Detector { - //private static final int MAX_MODULES = 32; - // Trick to avoid creating new Integer objects below -- a sort of crude copy of // the Integer.valueOf(int) optimization added in Java 5, not in J2ME private static final Integer[] INTEGERS = { new Integer(0), new Integer(1), new Integer(2), new Integer(3), new Integer(4) }; + // No, can't use valueOf() - private final MonochromeBitmapSource image; - private final MonochromeRectangleDetector rectangleDetector; + private final BitMatrix image; + private final WhiteRectangleDetector rectangleDetector; - public Detector(MonochromeBitmapSource image) { + public Detector(BitMatrix image) { this.image = image; - rectangleDetector = new MonochromeRectangleDetector(image); + rectangleDetector = new WhiteRectangleDetector(image); } /** *

Detects a Data Matrix Code in an image.

* - * @return {@link DetectorResult} encapsulating results of detecting a QR Code - * @throws ReaderException if no Data Matrix Code can be found + * @return {@link DetectorResult} encapsulating results of detecting a Data Matrix Code + * @throws NotFoundException if no Data Matrix Code can be found */ - public DetectorResult detect() throws ReaderException { + public DetectorResult detect() throws NotFoundException { ResultPoint[] cornerPoints = rectangleDetector.detect(); ResultPoint pointA = cornerPoints[0]; @@ -110,7 +108,7 @@ public final class Detector { } if (maybeTopLeft == null || bottomLeft == null || maybeBottomRight == null) { - throw ReaderException.getInstance(); + throw NotFoundException.getNotFoundInstance(); } // Bottom left is correct but top left and bottom right might be switched @@ -142,10 +140,8 @@ public final class Detector { // The top right point is actually the corner of a module, which is one of the two black modules // adjacent to the white module at the top right. Tracing to that corner from either the top left - // or bottom right should work here. The number of transitions could be higher than it should be - // due to noise. So we try both and take the min. - - int dimension = Math.min(transitionsBetween(topLeft, topRight).getTransitions(), + // or bottom right should work here. + int dimension = Math.min(transitionsBetween(topLeft, topRight).getTransitions(), transitionsBetween(bottomRight, topRight).getTransitions()); if ((dimension & 0x01) == 1) { // it can't be odd, so, round... up? @@ -153,8 +149,60 @@ public final class Detector { } dimension += 2; - BitMatrix bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, dimension); - return new DetectorResult(bits, new ResultPoint[] {pointA, pointB, pointC, pointD}); + //correct top right point to match the white module + ResultPoint correctedTopRight = correctTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension); + + //We redetermine the dimension using the corrected top right point + int dimension2 = Math.max(transitionsBetween(topLeft, correctedTopRight).getTransitions(), + transitionsBetween(bottomRight, correctedTopRight).getTransitions()); + dimension2++; + if ((dimension2 & 0x01) == 1) { + dimension2++; + } + + BitMatrix bits = sampleGrid(image, topLeft, bottomLeft, bottomRight, correctedTopRight, dimension2); + + return new DetectorResult(bits, new ResultPoint[]{topLeft, bottomLeft, bottomRight, correctedTopRight}); + } + + /** + * Calculates the position of the white top right module using the output of the rectangle detector + */ + private ResultPoint correctTopRight(ResultPoint bottomLeft, + ResultPoint bottomRight, + ResultPoint topLeft, + ResultPoint topRight, + int dimension) { + + float corr = distance(bottomLeft, bottomRight) / (float)dimension; + int norm = distance(topLeft, topRight); + float cos = (topRight.getX() - topLeft.getX()) / norm; + float sin = (topRight.getY() - topLeft.getY()) / norm; + + ResultPoint c1 = new ResultPoint(topRight.getX()+corr*cos, topRight.getY()+corr*sin); + + corr = distance(bottomLeft, bottomRight) / (float)dimension; + norm = distance(bottomRight, topRight); + cos = (topRight.getX() - bottomRight.getX()) / norm; + sin = (topRight.getY() - bottomRight.getY()) / norm; + + ResultPoint c2 = new ResultPoint(topRight.getX()+corr*cos, topRight.getY()+corr*sin); + + int l1 = Math.abs(transitionsBetween(topLeft, c1).getTransitions() - transitionsBetween(bottomRight, c1).getTransitions()); + int l2 = Math.abs(transitionsBetween(topLeft, c2).getTransitions() - transitionsBetween(bottomRight, c2).getTransitions()); + + if (l1 <= l2){ + return c1; + } + + return c2; + } + + // L2 distance + private static int distance(ResultPoint a, ResultPoint b) { + return (int) Math.round(Math.sqrt((a.getX() - b.getX()) + * (a.getX() - b.getX()) + (a.getY() - b.getY()) + * (a.getY() - b.getY()))); } /** @@ -165,40 +213,33 @@ public final class Detector { table.put(key, value == null ? INTEGERS[1] : INTEGERS[value.intValue() + 1]); } - private static BitMatrix sampleGrid(MonochromeBitmapSource image, + private static BitMatrix sampleGrid(BitMatrix image, ResultPoint topLeft, ResultPoint bottomLeft, ResultPoint bottomRight, - int dimension) throws ReaderException { - - // We make up the top right point for now, based on the others. - // TODO: we actually found a fourth corner above and figured out which of two modules - // it was the corner of. We could use that here and adjust for perspective distortion. - float topRightX = (bottomRight.getX() - bottomLeft.getX()) + topLeft.getX(); - float topRightY = (bottomRight.getY() - bottomLeft.getY()) + topLeft.getY(); + ResultPoint topRight, + int dimension) throws NotFoundException { - // Note that unlike in the QR Code sampler, we didn't find the center of modules, but the - // very corners. So there is no 0.5f here; 0.0f is right. GridSampler sampler = GridSampler.getInstance(); - return sampler.sampleGrid( - image, - dimension, - 0.0f, - 0.0f, - dimension, - 0.0f, - dimension, - dimension, - 0.0f, - dimension, - topLeft.getX(), - topLeft.getY(), - topRightX, - topRightY, - bottomRight.getX(), - bottomRight.getY(), - bottomLeft.getX(), - bottomLeft.getY()); + + return sampler.sampleGrid(image, + dimension, + 0.5f, + 0.5f, + dimension - 0.5f, + 0.5f, + dimension - 0.5f, + dimension - 0.5f, + 0.5f, + dimension - 0.5f, + topLeft.getX(), + topLeft.getY(), + topRight.getX(), + topRight.getY(), + bottomRight.getX(), + bottomRight.getY(), + bottomLeft.getX(), + bottomLeft.getY()); } /** @@ -226,15 +267,18 @@ public final class Detector { int ystep = fromY < toY ? 1 : -1; int xstep = fromX < toX ? 1 : -1; int transitions = 0; - boolean inBlack = image.isBlack(steep ? fromY : fromX, steep ? fromX : fromY); + boolean inBlack = image.get(steep ? fromY : fromX, steep ? fromX : fromY); for (int x = fromX, y = fromY; x != toX; x += xstep) { - boolean isBlack = image.isBlack(steep ? y : x, steep ? x : y); + boolean isBlack = image.get(steep ? y : x, steep ? x : y); if (isBlack != inBlack) { transitions++; inBlack = isBlack; } error += dy; if (error > 0) { + if (y == toY) { + break; + } y += ystep; error -= dx; }