Try more possible finder patterns, but be stricter about vetting them. Produces about a 30% increase in accuracy on our test cases.

git-svn-id: https://zxing.googlecode.com/svn/trunk@244 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
srowen 2008-03-04 20:42:34 +00:00
parent e3d418f458
commit c82d0790c3
3 changed files with 36 additions and 16 deletions

View file

@ -164,7 +164,7 @@ final class AlignmentPatternFinder {
*/
private boolean foundPatternCross(int[] stateCount) {
float moduleSize = this.moduleSize;
float maxVariance = moduleSize / 2.5f;
float maxVariance = moduleSize / 2.0f;
for (int i = 0; i < 3; i++) {
if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {
return false;
@ -184,7 +184,7 @@ final class AlignmentPatternFinder {
* observed in any reading state, based on the results of the horizontal scan
* @return vertical center of alignment pattern, or {@link Float#NaN} if not found
*/
private float crossCheckVertical(int startI, int centerJ, int maxCount) {
private float crossCheckVertical(int startI, int centerJ, int maxCount, int originalStateCountTotal) {
MonochromeBitmapSource image = this.image;
int maxI = image.getHeight();
@ -225,6 +225,11 @@ final class AlignmentPatternFinder {
return Float.NaN;
}
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
return Float.NaN;
}
return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : Float.NaN;
}
@ -240,8 +245,9 @@ final class AlignmentPatternFinder {
* @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not
*/
private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) {
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
float centerJ = centerFromEnd(stateCount, j);
float centerI = crossCheckVertical(i, (int) centerJ, 2 * stateCount[1]);
float centerI = crossCheckVertical(i, (int) centerJ, 2 * stateCount[1], stateCountTotal);
if (!Float.isNaN(centerI)) {
float estimatedModuleSize = (float) (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f;
int max = possibleCenters.size();

View file

@ -62,14 +62,14 @@ public final class Detector {
Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension);
int modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7;
// Guess where a "bottom right" finder pattern would have been
float bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();
float bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();
AlignmentPattern alignmentPattern = null;
// Anything above version 1 has an alignment pattern
if (provisionalVersion.getAlignmentPatternCenters().length > 0) {
// Guess where a "bottom right" finder pattern would have been
float bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();
float bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();
// Estimate that alignment pattern is closer by 3 modules
// from "bottom right" to known top left location
float correctionToTopLeft = 1.0f - 3.0f / (float) modulesBetweenFPCenters;

View file

@ -179,8 +179,8 @@ final class FinderPatternFinder {
return false;
}
float moduleSize = (float) totalModuleSize / 7.0f;
float maxVariance = moduleSize / 2.5f;
// Allow less than 40% variance from 1-1-3-1-1 proportions
float maxVariance = moduleSize / 2.0f;
// Allow less than 50% variance from 1-1-3-1-1 proportions
return Math.abs(moduleSize - stateCount[0]) < maxVariance &&
Math.abs(moduleSize - stateCount[1]) < maxVariance &&
Math.abs(3.0f * moduleSize - stateCount[2]) < 3.0f * maxVariance &&
@ -199,7 +199,7 @@ final class FinderPatternFinder {
* observed in any reading state, based on the results of the horizontal scan
* @return vertical center of finder pattern, or {@link Float#NaN} if not found
*/
private float crossCheckVertical(int startI, int centerJ, int maxCount) {
private float crossCheckVertical(int startI, int centerJ, int maxCount, int originalStateCountTotal) {
MonochromeBitmapSource image = this.image;
int maxI = image.getHeight();
@ -254,15 +254,22 @@ final class FinderPatternFinder {
return Float.NaN;
}
// If we found a finder-pattern-like section, but its size is more than 20% different than
// the original, assume it's a false positive
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
return Float.NaN;
}
return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : Float.NaN;
}
/**
* <p>Like {@link #crossCheckVertical(int, int, int)}, and in fact is basically identical,
* <p>Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical,
* except it reads horizontally instead of vertically. This is used to cross-cross
* check a vertical cross check and locate the real center of the alignment pattern.</p>
*/
private float crossCheckHorizontal(int startJ, int centerI, int maxCount) {
private float crossCheckHorizontal(int startJ, int centerI, int maxCount, int originalStateCountTotal) {
MonochromeBitmapSource image = this.image;
int maxJ = image.getWidth();
@ -314,6 +321,13 @@ final class FinderPatternFinder {
return Float.NaN;
}
// If we found a finder-pattern-like section, but its size is significantly different than
// the original, assume it's a false positive
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
return Float.NaN;
}
return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : Float.NaN;
}
@ -336,14 +350,14 @@ final class FinderPatternFinder {
private boolean handlePossibleCenter(int[] stateCount,
int i,
int j) {
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
float centerJ = centerFromEnd(stateCount, j);
float centerI = crossCheckVertical(i, (int) centerJ, stateCount[2]);
float centerI = crossCheckVertical(i, (int) centerJ, stateCount[2], stateCountTotal);
if (!Float.isNaN(centerI)) {
// Re-cross check
centerJ = crossCheckHorizontal((int) centerJ, (int) centerI, stateCount[2]);
centerJ = crossCheckHorizontal((int) centerJ, (int) centerI, stateCount[2], stateCountTotal);
if (!Float.isNaN(centerJ)) {
float estimatedModuleSize =
(float) (stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]) / 7.0f;
float estimatedModuleSize = (float) stateCountTotal / 7.0f;
boolean found = false;
int max = possibleCenters.size();
for (int index = 0; index < max; index++) {