diff --git a/core/build.xml b/core/build.xml index e2df078db..ab16bd13f 100644 --- a/core/build.xml +++ b/core/build.xml @@ -139,6 +139,7 @@ + diff --git a/core/test/data/blackbox/falsepositives/06.jpg b/core/test/data/blackbox/falsepositives/06.jpg index 65cc1e2af..1d121c53e 100644 Binary files a/core/test/data/blackbox/falsepositives/06.jpg and b/core/test/data/blackbox/falsepositives/06.jpg differ diff --git a/core/test/data/blackbox/falsepositives/07.jpg b/core/test/data/blackbox/falsepositives/07.jpg index 770c9d418..69e4b4750 100644 Binary files a/core/test/data/blackbox/falsepositives/07.jpg and b/core/test/data/blackbox/falsepositives/07.jpg differ diff --git a/core/test/data/blackbox/falsepositives/08.jpg b/core/test/data/blackbox/falsepositives/08.jpg index 3146ff7b5..57fc13de1 100644 Binary files a/core/test/data/blackbox/falsepositives/08.jpg and b/core/test/data/blackbox/falsepositives/08.jpg differ diff --git a/core/test/data/blackbox/falsepositives/13.jpg b/core/test/data/blackbox/falsepositives/13.jpg index 32cd980f3..80960da72 100644 Binary files a/core/test/data/blackbox/falsepositives/13.jpg and b/core/test/data/blackbox/falsepositives/13.jpg differ diff --git a/core/test/data/blackbox/falsepositives/23.jpg b/core/test/data/blackbox/falsepositives/23.jpg deleted file mode 100644 index 1d121c53e..000000000 Binary files a/core/test/data/blackbox/falsepositives/23.jpg and /dev/null differ diff --git a/core/test/data/blackbox/falsepositives/24.jpg b/core/test/data/blackbox/falsepositives/24.jpg deleted file mode 100644 index 69e4b4750..000000000 Binary files a/core/test/data/blackbox/falsepositives/24.jpg and /dev/null differ diff --git a/core/test/data/blackbox/falsepositives/25.jpg b/core/test/data/blackbox/falsepositives/25.jpg deleted file mode 100644 index 57fc13de1..000000000 Binary files a/core/test/data/blackbox/falsepositives/25.jpg and /dev/null differ diff --git a/core/test/data/blackbox/falsepositives/26.jpg b/core/test/data/blackbox/falsepositives/26.jpg deleted file mode 100644 index 80960da72..000000000 Binary files a/core/test/data/blackbox/falsepositives/26.jpg and /dev/null differ diff --git a/core/test/src/com/google/zxing/common/AbstractNegativeBlackBoxTestCase.java b/core/test/src/com/google/zxing/common/AbstractNegativeBlackBoxTestCase.java new file mode 100644 index 000000000..db55393c8 --- /dev/null +++ b/core/test/src/com/google/zxing/common/AbstractNegativeBlackBoxTestCase.java @@ -0,0 +1,129 @@ +/* + * Copyright 2008 ZXing authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.zxing.common; + +import com.google.zxing.MonochromeBitmapSource; +import com.google.zxing.MultiFormatReader; +import com.google.zxing.ReaderException; +import com.google.zxing.Result; +import com.google.zxing.client.j2se.BufferedImageMonochromeBitmapSource; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Vector; + +/** + * This abstract class looks for negative results, i.e. it only allows a certain number of false + * positives in images which should not decode. This helps ensure that we are not too lenient. + * + * @author dswitkin@google.com (Daniel Switkin) + */ +public abstract class AbstractNegativeBlackBoxTestCase extends AbstractBlackBoxTestCase { + + private static class TestResult { + private final int falsePositivesAllowed; + private final float rotation; + + TestResult(int falsePositivesAllowed, float rotation) { + this.falsePositivesAllowed = falsePositivesAllowed; + this.rotation = rotation; + } + + public int getFalsePositivesAllowed() { + return falsePositivesAllowed; + } + + public float getRotation() { + return rotation; + } + } + + private Vector testResults; + + // Use the multiformat reader to evaluate all decoders in the system. + protected AbstractNegativeBlackBoxTestCase(File testBase) { + super(testBase, new MultiFormatReader(), null); + testResults = new Vector(); + } + + protected void addTest(int falsePositivesAllowed, float rotation) { + testResults.add(new TestResult(falsePositivesAllowed, rotation)); + } + + @Override + public void testBlackBox() throws IOException { + assertFalse(testResults.isEmpty()); + + File[] imageFiles = getImageFiles(); + int[] falsePositives = new int[testResults.size()]; + for (File testImage : imageFiles) { + System.out.println("Starting " + testImage.getAbsolutePath()); + + BufferedImage image = ImageIO.read(testImage); + if (image == null) { + throw new IOException("Could not read image: " + testImage); + } + for (int x = 0; x < testResults.size(); x++) { + if (!checkForFalsePositives(image, testResults.get(x).getRotation())) { + falsePositives[x]++; + } + } + } + + for (int x = 0; x < testResults.size(); x++) { + System.out.println("Rotation " + testResults.get(x).getRotation() + " degrees: " + + falsePositives[x] + " of " + imageFiles.length + " images were false positives (" + + testResults.get(x).getFalsePositivesAllowed() + " allowed)"); + assertTrue("Rotation " + testResults.get(x).getRotation() + " degrees: " + + "Too many false positives found", + falsePositives[x] <= testResults.get(x).getFalsePositivesAllowed()); + } + } + + /** + * Make sure ZXing does NOT find a barcode in the image. + * + * @param image The image to test + * @param rotationInDegrees The amount of rotation to apply + * @return true if nothing found, false if a non-existant barcode was detected + */ + private boolean checkForFalsePositives(BufferedImage image, float rotationInDegrees) { + BufferedImage rotatedImage = rotateImage(image, rotationInDegrees); + MonochromeBitmapSource source = new BufferedImageMonochromeBitmapSource(rotatedImage); + Result result; + try { + result = getReader().decode(source); + System.out.println("Found false positive: '" + result.getText() + "' with format '" + + result.getBarcodeFormat() + "' (rotation: " + rotationInDegrees + ')'); + return false; + } catch (ReaderException re) { + } + + // Try "try harder" mode + try { + result = getReader().decode(source, TRY_HARDER_HINT); + System.out.println("Try harder found false positive: '" + result.getText() + "' with format '" + + result.getBarcodeFormat() + "' (rotation: " + rotationInDegrees + ')'); + return false; + } catch (ReaderException re) { + } + return true; + } + +} \ No newline at end of file diff --git a/core/test/src/com/google/zxing/common/FalsePositivesBlackBoxTestCase.java b/core/test/src/com/google/zxing/common/FalsePositivesBlackBoxTestCase.java index 771798c04..83df937a4 100644 --- a/core/test/src/com/google/zxing/common/FalsePositivesBlackBoxTestCase.java +++ b/core/test/src/com/google/zxing/common/FalsePositivesBlackBoxTestCase.java @@ -16,85 +16,21 @@ package com.google.zxing.common; -import com.google.zxing.MonochromeBitmapSource; -import com.google.zxing.MultiFormatReader; -import com.google.zxing.ReaderException; -import com.google.zxing.Result; -import com.google.zxing.client.j2se.BufferedImageMonochromeBitmapSource; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; import java.io.File; -import java.io.IOException; /** - * This test ensures that random, noisy, or unsupported barcode images do not decode. + * This test ensures that random images with high contrast patterns do not decode as barcodes. * * @author dswitkin@google.com (Daniel Switkin) */ -public final class FalsePositivesBlackBoxTestCase extends AbstractBlackBoxTestCase { +public final class FalsePositivesBlackBoxTestCase extends AbstractNegativeBlackBoxTestCase { - // This number should be reduced as we get better at rejecting false positives. - private static final int FALSE_POSITIVES_ALLOWED = 4; - - // Use the multiformat reader to evaluate all decoders in the system. public FalsePositivesBlackBoxTestCase() { - super(new File("test/data/blackbox/falsepositives"), new MultiFormatReader(), null); - } - - @Override - public void testBlackBox() throws IOException { - File[] imageFiles = getImageFiles(); - int falsePositives = 0; - for (File testImage : imageFiles) { - System.out.println("Starting " + testImage.getAbsolutePath()); - - // Try all four rotations, since many of the test images don't have a notion of up, and we - // want to be as robust as possible. - BufferedImage image = ImageIO.read(testImage); - if (image == null) { - throw new IOException("Could not read image: " + testImage); - } - for (int x = 0; x < 4; x++) { - if (!checkForFalsePositives(image, x * 90.0f)) { - falsePositives++; - } - } - } - - System.out.println("Found " + falsePositives + " false positives (" + FALSE_POSITIVES_ALLOWED + - " max)"); - assertTrue("Too many false positives found", falsePositives <= FALSE_POSITIVES_ALLOWED); - } - - /** - * Make sure ZXing does NOT find a barcode in the image. - * - * @param image The image to test - * @param rotationInDegrees The amount of rotation to apply - * @return true if nothing found, false if a non-existant barcode was detected - */ - private boolean checkForFalsePositives(BufferedImage image, float rotationInDegrees) { - BufferedImage rotatedImage = rotateImage(image, rotationInDegrees); - MonochromeBitmapSource source = new BufferedImageMonochromeBitmapSource(rotatedImage); - Result result; - try { - result = getReader().decode(source); - System.out.println("Found false positive: '" + result.getText() + "' with format '" + - result.getBarcodeFormat() + "' (rotation: " + rotationInDegrees + ')'); - return false; - } catch (ReaderException re) { - } - - // Try "try harder" mode - try { - result = getReader().decode(source, TRY_HARDER_HINT); - System.out.println("Try harder found false positive: '" + result.getText() + "' with format '" + - result.getBarcodeFormat() + "' (rotation: " + rotationInDegrees + ')'); - return false; - } catch (ReaderException re) { - } - return true; + super(new File("test/data/blackbox/falsepositives")); + addTest(1, 0.0f); + addTest(1, 90.0f); + addTest(1, 180.0f); + addTest(0, 270.0f); } }