Count misreads in the test framework and track. Retune slightly on this basis to pick up a few more images

git-svn-id: https://zxing.googlecode.com/svn/trunk@2116 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2012-01-13 14:38:38 +00:00
parent 28a0ceb67d
commit 5415b12050
18 changed files with 164 additions and 94 deletions

View file

@ -44,7 +44,7 @@ public abstract class UPCEANReader extends OneDReader {
// These two values are critical for determining how permissive the decoding will be.
// We've arrived at these values through a lot of trial and error. Setting them any higher
// lets false positives creep in quickly.
private static final int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);
private static final int MAX_AVG_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.48f);
private static final int MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.7f);
/**

View file

@ -83,15 +83,26 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
testResults = new ArrayList<TestResult>();
}
protected void addTest(int mustPassCount, int tryHarderCount, float rotation) {
addTest(mustPassCount, tryHarderCount, 0, 0, rotation);
}
/**
* Adds a new test for the current directory of images.
*
* @param mustPassCount The number of images which must decode for the test to pass.
* @param tryHarderCount The number of images which must pass using the try harder flag.
* @param maxMisreads Maximum number of images which can fail due to successfully reading the wrong contents
* @param maxTryHarderMisreads Maximum number of images which can fail due to successfully
* reading the wrong contents using the try harder flag
* @param rotation The rotation in degrees clockwise to use for this test.
*/
protected void addTest(int mustPassCount, int tryHarderCount, float rotation) {
testResults.add(new TestResult(mustPassCount, tryHarderCount, rotation));
protected void addTest(int mustPassCount,
int tryHarderCount,
int maxMisreads,
int maxTryHarderMisreads,
float rotation) {
testResults.add(new TestResult(mustPassCount, tryHarderCount, maxMisreads, maxTryHarderMisreads, rotation));
}
protected File[] getImageFiles() {
@ -115,10 +126,14 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
File[] imageFiles = getImageFiles();
int testCount = testResults.size();
int[] passedCounts = new int[testCount];
int[] misreadCounts = new int[testCount];
int[] tryHarderCounts = new int[testCount];
int[] tryHaderMisreadCounts = new int[testCount];
for (File testImage : imageFiles) {
System.out.println("Starting " + testImage.getAbsolutePath());
System.out.printf("Starting %s\n", testImage.getAbsolutePath());
BufferedImage image = ImageIO.read(testImage);
@ -143,11 +158,23 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
BufferedImage rotatedImage = rotateImage(image, rotation);
LuminanceSource source = new BufferedImageLuminanceSource(rotatedImage);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
if (decode(bitmap, rotation, expectedText, expectedMetadata, false)) {
passedCounts[x]++;
try {
if (decode(bitmap, rotation, expectedText, expectedMetadata, false)) {
passedCounts[x]++;
} else {
misreadCounts[x]++;
}
} catch (ReaderException re) {
// continue
}
if (decode(bitmap, rotation, expectedText, expectedMetadata, true)) {
tryHarderCounts[x]++;
try {
if (decode(bitmap, rotation, expectedText, expectedMetadata, true)) {
tryHarderCounts[x]++;
} else {
tryHaderMisreadCounts[x]++;
}
} catch (ReaderException re) {
// continue
}
}
}
@ -155,37 +182,59 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
// Print the results of all tests first
int totalFound = 0;
int totalMustPass = 0;
for (int x = 0; x < testCount; x++) {
System.out.println("Rotation " + testResults.get(x).getRotation() + " degrees:");
System.out.println(" " + passedCounts[x] + " of " + imageFiles.length + " images passed ("
+ testResults.get(x).getMustPassCount() + " required)");
System.out.println(" " + tryHarderCounts[x] + " of " + imageFiles.length +
" images passed with try harder (" + testResults.get(x).getTryHarderCount() +
" required)");
totalFound += passedCounts[x];
totalFound += tryHarderCounts[x];
totalMustPass += testResults.get(x).getMustPassCount();
totalMustPass += testResults.get(x).getTryHarderCount();
int totalMisread = 0;
int totalMaxMisread = 0;
for (int x = 0; x < testResults.size(); x++) {
TestResult testResult = testResults.get(x);
System.out.printf("Rotation %d degrees:\n", (int) testResult.getRotation());
System.out.printf(" %d of %d images passed (%d required)\n",
passedCounts[x], imageFiles.length, testResult.getMustPassCount());
int failed = imageFiles.length - passedCounts[x];
System.out.printf(" %d failed due to misreads, %d not detected\n",
misreadCounts[x], failed - misreadCounts[x]);
System.out.printf(" %d of %d images passed with try harder (%d required)\n",
tryHarderCounts[x], imageFiles.length, testResult.getTryHarderCount());
failed = imageFiles.length - tryHarderCounts[x];
System.out.printf(" %d failed due to misreads, %d not detected\n",
tryHaderMisreadCounts[x], failed - tryHaderMisreadCounts[x]);
totalFound += passedCounts[x] + tryHarderCounts[x];
totalMustPass += testResult.getMustPassCount() + testResult.getTryHarderCount();
totalMisread += misreadCounts[x] + tryHaderMisreadCounts[x];
totalMaxMisread += testResult.getMaxMisreads() + testResult.getMaxTryHarderMisreads();
}
int totalTests = imageFiles.length * testCount * 2;
System.out.println("TOTALS:\n Decoded " + totalFound + " images out of " + totalTests +
" (" + (totalFound * 100 / totalTests) + "%, " + totalMustPass + " required)");
System.out.printf("TOTALS:\nDecoded %d images out of %d (%d%%, %d required)\n",
totalFound, totalTests, totalFound * 100 / totalTests, totalMustPass);
if (totalFound > totalMustPass) {
System.out.println(" *** Test too lax by " + (totalFound - totalMustPass) + " images");
System.out.printf(" +++ Test too lax by %d images\n", totalFound - totalMustPass);
} else if (totalFound < totalMustPass) {
System.out.println(" *** Test failed by " + (totalMustPass - totalFound) + " images");
System.out.printf(" --- Test failed by %d images\n", totalMustPass - totalFound);
}
if (totalMisread < totalMaxMisread) {
System.out.printf(" +++ Test expects too many misreads by %d images\n", totalMaxMisread - totalMisread);
} else if (totalMisread > totalMaxMisread) {
System.out.printf(" --- Test had too many misreads by %d images\n", totalMisread - totalMaxMisread);
}
System.out.flush();
// Then run through again and assert if any failed
if (assertOnFailure) {
for (int x = 0; x < testCount; x++) {
assertTrue("Rotation " + testResults.get(x).getRotation() +
" degrees: Too many images failed",
passedCounts[x] >= testResults.get(x).getMustPassCount());
assertTrue("Try harder, Rotation " + testResults.get(x).getRotation() +
" degrees: Too many images failed",
tryHarderCounts[x] >= testResults.get(x).getTryHarderCount());
TestResult testResult = testResults.get(x);
String label = "Rotation " + testResult.getRotation() + " degrees: Too many images failed";
assertTrue(label,
passedCounts[x] >= testResult.getMustPassCount());
assertTrue("Try harder, " + label,
tryHarderCounts[x] >= testResult.getTryHarderCount());
label = "Rotation " + testResult.getRotation() + " degrees: Too many images misread";
assertTrue(label,
misreadCounts[x] <= testResult.getMaxMisreads());
assertTrue("Try harder, " + label,
tryHaderMisreadCounts[x] <= testResult.getMaxTryHarderMisreads());
}
}
return new SummaryResults(totalFound, totalMustPass, totalTests);
@ -195,33 +244,27 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
float rotation,
String expectedText,
Map<?,?> expectedMetadata,
boolean tryHarder) {
boolean tryHarder) throws ReaderException {
String suffix = " (" + (tryHarder ? "try harder, " : "") + "rotation: " + rotation + ')';
String suffix = String.format(" (%srotation: %d)", tryHarder ? "try harder, " : "", (int) rotation);
Map<DecodeHintType,Object> hints = new EnumMap<DecodeHintType,Object>(DecodeHintType.class);
if (tryHarder) {
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
}
Result result;
try {
result = barcodeReader.decode(source, hints);
} catch (ReaderException re) {
System.out.println(re + suffix);
return false;
}
Result result = barcodeReader.decode(source, hints);
if (expectedFormat != result.getBarcodeFormat()) {
System.out.println("Format mismatch: expected '" + expectedFormat + "' but got '" +
result.getBarcodeFormat() + '\'' + suffix);
System.out.printf("Format mismatch: expected '%s' but got '%s'%s\n",
expectedFormat, result.getBarcodeFormat(), suffix);
return false;
}
String resultText = result.getText();
if (!expectedText.equals(resultText)) {
System.out.println("Mismatch: expected '" + expectedText + "' but got '" + resultText +
'\'' + suffix);
System.out.printf("Content mismatch: expected '%s' but got '%s'%s\n",
expectedText, resultText, suffix);
return false;
}
@ -231,8 +274,8 @@ public abstract class AbstractBlackBoxTestCase extends Assert {
Object expectedValue = metadatum.getValue();
Object actualValue = resultMetadata == null ? null : resultMetadata.get(key);
if (!expectedValue.equals(actualValue)) {
System.out.println("Metadata mismatch: for key '" + key + "' expected '" + expectedValue +
"' but got '" + actualValue + '\'');
System.out.printf("Metadata mismatch for key '%s': expected '%s' but got '%s'\n",
key, expectedValue, actualValue);
return false;
}
}

View file

@ -80,26 +80,42 @@ public abstract class AbstractNegativeBlackBoxTestCase extends AbstractBlackBoxT
File[] imageFiles = getImageFiles();
int[] falsePositives = new int[testResults.size()];
for (File testImage : imageFiles) {
System.out.println("Starting " + testImage.getAbsolutePath());
System.out.printf("Starting %s\n", 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())) {
TestResult testResult = testResults.get(x);
if (!checkForFalsePositives(image, testResult.getRotation())) {
falsePositives[x]++;
}
}
}
int totalFalsePositives = 0;
int totalAllowed = 0;
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());
TestResult testResult = testResults.get(x);
totalFalsePositives += falsePositives[x];
totalAllowed += testResult.getFalsePositivesAllowed();
}
if (totalFalsePositives < totalAllowed) {
System.out.printf(" +++ Test too lax by %d images\n", totalAllowed - totalFalsePositives);
} else if (totalFalsePositives > totalAllowed) {
System.out.printf(" --- Test failed by %d images\n", totalFalsePositives - totalAllowed);
}
for (int x = 0; x < testResults.size(); x++) {
TestResult testResult = testResults.get(x);
System.out.printf("Rotation %d degrees: %d of %d images were false positives (%d allowed)\n",
(int) testResult.getRotation(), falsePositives[x], imageFiles.length,
testResult.getFalsePositivesAllowed());
assertTrue("Rotation " + testResult.getRotation() + " degrees: Too many false positives found",
falsePositives[x] <= testResult.getFalsePositivesAllowed());
}
}
@ -117,8 +133,8 @@ public abstract class AbstractNegativeBlackBoxTestCase extends AbstractBlackBoxT
Result result;
try {
result = getReader().decode(bitmap);
System.out.println("Found false positive: '" + result.getText() + "' with format '" +
result.getBarcodeFormat() + "' (rotation: " + rotationInDegrees + ')');
System.out.printf("Found false positive: '%s' with format '%s' (rotation: %d)\n",
result.getText(), result.getBarcodeFormat(), (int) rotationInDegrees);
return false;
} catch (ReaderException re) {
}
@ -128,9 +144,8 @@ public abstract class AbstractNegativeBlackBoxTestCase extends AbstractBlackBoxT
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
try {
result = getReader().decode(bitmap, hints);
System.out.println("Try harder found false positive: '" + result.getText() +
"' with format '" + result.getBarcodeFormat() + "' (rotation: " +
rotationInDegrees + ')');
System.out.printf("Try harder found false positive: '%s' with format '%s' (rotation: %d)\n",
result.getText(), result.getBarcodeFormat(), (int) rotationInDegrees);
return false;
} catch (ReaderException re) {
}

View file

@ -20,11 +20,15 @@ final class TestResult {
private final int mustPassCount;
private final int tryHarderCount;
private final int maxMisreads;
private final int maxTryHarderMisreads;
private final float rotation;
TestResult(int mustPassCount, int tryHarderCount, float rotation) {
TestResult(int mustPassCount, int tryHarderCount, int maxMisreads, int maxTryHarderMisreads, float rotation) {
this.mustPassCount = mustPassCount;
this.tryHarderCount = tryHarderCount;
this.maxMisreads = maxMisreads;
this.maxTryHarderMisreads = maxTryHarderMisreads;
this.rotation = rotation;
}
@ -35,6 +39,14 @@ final class TestResult {
int getTryHarderCount() {
return tryHarderCount;
}
int getMaxMisreads() {
return maxMisreads;
}
int getMaxTryHarderMisreads() {
return maxTryHarderMisreads;
}
float getRotation() {
return rotation;

View file

@ -27,10 +27,10 @@ public final class DataMatrixBlackBox2TestCase extends AbstractBlackBoxTestCase
public DataMatrixBlackBox2TestCase() {
super("test/data/blackbox/datamatrix-2", new MultiFormatReader(), BarcodeFormat.DATA_MATRIX);
addTest(8, 8, 0.0f);
addTest(14, 14, 90.0f);
addTest(14, 14, 180.0f);
addTest(12, 12, 270.0f);
addTest(8, 8, 0, 1, 0.0f);
addTest(14, 14, 0, 1, 90.0f);
addTest(14, 14, 0, 1, 180.0f);
addTest(12, 12, 0, 1, 270.0f);
}
}

View file

@ -27,10 +27,10 @@ public final class FalsePositives2BlackBoxTestCase extends AbstractNegativeBlack
public FalsePositives2BlackBoxTestCase() {
super("test/data/blackbox/falsepositives-2");
addTest(7, 0.0f);
addTest(7, 90.0f);
addTest(7, 180.0f);
addTest(7, 270.0f);
addTest(5, 0.0f);
addTest(5, 90.0f);
addTest(5, 180.0f);
addTest(5, 270.0f);
}
}

View file

@ -27,10 +27,10 @@ public final class FalsePositivesBlackBoxTestCase extends AbstractNegativeBlackB
public FalsePositivesBlackBoxTestCase() {
super("test/data/blackbox/falsepositives");
addTest(1, 0.0f);
addTest(0, 90.0f);
addTest(0, 180.0f);
addTest(1, 270.0f);
addTest(2, 0.0f);
addTest(2, 90.0f);
addTest(2, 180.0f);
addTest(2, 270.0f);
}
}

View file

@ -27,10 +27,10 @@ public final class PartialBlackBoxTestCase extends AbstractNegativeBlackBoxTestC
public PartialBlackBoxTestCase() {
super("test/data/blackbox/partial");
addTest(1, 0.0f);
addTest(1, 90.0f);
addTest(1, 180.0f);
addTest(1, 270.0f);
addTest(2, 0.0f);
addTest(2, 90.0f);
addTest(2, 180.0f);
addTest(2, 270.0f);
}
}

View file

@ -29,8 +29,8 @@ public final class EAN13BlackBox2TestCase extends AbstractBlackBoxTestCase {
public EAN13BlackBox2TestCase() {
super("test/data/blackbox/ean13-2", new MultiFormatReader(), BarcodeFormat.EAN_13);
addTest(11, 16, 0.0f);
addTest(10, 16, 180.0f);
addTest(12, 17, 0, 1, 0.0f);
addTest(11, 17, 0, 1, 180.0f);
}
}

View file

@ -28,8 +28,8 @@ public final class EAN13BlackBox4TestCase extends AbstractBlackBoxTestCase {
public EAN13BlackBox4TestCase() {
super("test/data/blackbox/ean13-4", new MultiFormatReader(), BarcodeFormat.EAN_13);
addTest(6, 13, 0.0f);
addTest(7, 13, 180.0f);
addTest(6, 13, 1, 1, 0.0f);
addTest(7, 13, 1, 1, 180.0f);
}
}

View file

@ -27,8 +27,8 @@ public final class UPCABlackBox1TestCase extends AbstractBlackBoxTestCase {
public UPCABlackBox1TestCase() {
super("test/data/blackbox/upca-1", new MultiFormatReader(), BarcodeFormat.UPC_A);
addTest(14, 18, 0.0f);
addTest(16, 18, 180.0f);
addTest(14, 18, 0, 1, 0.0f);
addTest(16, 18, 0, 1, 180.0f);
}
}

View file

@ -27,8 +27,8 @@ public final class UPCABlackBox2TestCase extends AbstractBlackBoxTestCase {
public UPCABlackBox2TestCase() {
super("test/data/blackbox/upca-2", new MultiFormatReader(), BarcodeFormat.UPC_A);
addTest(29, 35, 0.0f);
addTest(31, 35, 180.0f);
addTest(30, 36, 0, 2, 0.0f);
addTest(31, 36, 0, 2, 180.0f);
}
}

View file

@ -27,8 +27,8 @@ public final class UPCABlackBox3ReflectiveTestCase extends AbstractBlackBoxTestC
public UPCABlackBox3ReflectiveTestCase() {
super("test/data/blackbox/upca-3", new MultiFormatReader(), BarcodeFormat.UPC_A);
addTest(7, 8, 0.0f);
addTest(8, 9, 180.0f);
addTest(7, 9, 0, 2, 0.0f);
addTest(8, 9, 0, 2, 180.0f);
}
}

View file

@ -27,8 +27,8 @@ public final class UPCABlackBox4TestCase extends AbstractBlackBoxTestCase {
public UPCABlackBox4TestCase() {
super("test/data/blackbox/upca-4", new MultiFormatReader(), BarcodeFormat.UPC_A);
addTest(9, 11, 0.0f);
addTest(9, 11, 180.0f);
addTest(9, 11, 0, 1, 0.0f);
addTest(9, 11, 0, 1, 180.0f);
}
}

View file

@ -27,8 +27,8 @@ public final class UPCABlackBox5TestCase extends AbstractBlackBoxTestCase {
public UPCABlackBox5TestCase() {
super("test/data/blackbox/upca-5", new MultiFormatReader(), BarcodeFormat.UPC_A);
addTest(19, 23, 0.0f);
addTest(20, 23, 180.0f);
addTest(19, 23, 1, 1, 0.0f);
addTest(21, 23, 0, 1, 180.0f);
}
}

View file

@ -27,8 +27,8 @@ public final class UPCEBlackBox2TestCase extends AbstractBlackBoxTestCase {
public UPCEBlackBox2TestCase() {
super("test/data/blackbox/upce-2", new MultiFormatReader(), BarcodeFormat.UPC_E);
addTest(30, 35, 0.0f);
addTest(31, 35, 180.0f);
addTest(31, 35, 0, 1, 0.0f);
addTest(31, 35, 1, 1, 180.0f);
}
}

View file

@ -27,8 +27,8 @@ public final class RSS14BlackBox2TestCase extends AbstractBlackBoxTestCase {
public RSS14BlackBox2TestCase() {
super("test/data/blackbox/rss14-2", new MultiFormatReader(), BarcodeFormat.RSS_14);
addTest(3, 8, 0.0f);
addTest(2, 8, 180.0f);
addTest(3, 8, 1, 1, 0.0f);
addTest(2, 8, 0, 1, 180.0f);
}
}

View file

@ -29,8 +29,8 @@ public final class PDF417BlackBox2TestCase extends AbstractBlackBoxTestCase {
public PDF417BlackBox2TestCase() {
super("test/data/blackbox/pdf417-2", new MultiFormatReader(), BarcodeFormat.PDF_417);
addTest(15, 15, 0.0f);
addTest(14, 14, 180.0f);
addTest(15, 15, 3, 3, 0.0f);
addTest(14, 14, 1, 1, 180.0f);
}
}