mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
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:
parent
e3d418f458
commit
c82d0790c3
|
@ -164,7 +164,7 @@ final class AlignmentPatternFinder {
|
||||||
*/
|
*/
|
||||||
private boolean foundPatternCross(int[] stateCount) {
|
private boolean foundPatternCross(int[] stateCount) {
|
||||||
float moduleSize = this.moduleSize;
|
float moduleSize = this.moduleSize;
|
||||||
float maxVariance = moduleSize / 2.5f;
|
float maxVariance = moduleSize / 2.0f;
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {
|
if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -184,7 +184,7 @@ final class AlignmentPatternFinder {
|
||||||
* observed in any reading state, based on the results of the horizontal scan
|
* 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
|
* @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;
|
MonochromeBitmapSource image = this.image;
|
||||||
|
|
||||||
int maxI = image.getHeight();
|
int maxI = image.getHeight();
|
||||||
|
@ -225,6 +225,11 @@ final class AlignmentPatternFinder {
|
||||||
return Float.NaN;
|
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;
|
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
|
* @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not
|
||||||
*/
|
*/
|
||||||
private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) {
|
private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) {
|
||||||
|
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
|
||||||
float centerJ = centerFromEnd(stateCount, j);
|
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)) {
|
if (!Float.isNaN(centerI)) {
|
||||||
float estimatedModuleSize = (float) (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f;
|
float estimatedModuleSize = (float) (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f;
|
||||||
int max = possibleCenters.size();
|
int max = possibleCenters.size();
|
||||||
|
|
|
@ -62,14 +62,14 @@ public final class Detector {
|
||||||
Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension);
|
Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension);
|
||||||
int modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7;
|
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;
|
AlignmentPattern alignmentPattern = null;
|
||||||
// Anything above version 1 has an alignment pattern
|
// Anything above version 1 has an alignment pattern
|
||||||
if (provisionalVersion.getAlignmentPatternCenters().length > 0) {
|
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
|
// Estimate that alignment pattern is closer by 3 modules
|
||||||
// from "bottom right" to known top left location
|
// from "bottom right" to known top left location
|
||||||
float correctionToTopLeft = 1.0f - 3.0f / (float) modulesBetweenFPCenters;
|
float correctionToTopLeft = 1.0f - 3.0f / (float) modulesBetweenFPCenters;
|
||||||
|
|
|
@ -179,8 +179,8 @@ final class FinderPatternFinder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
float moduleSize = (float) totalModuleSize / 7.0f;
|
float moduleSize = (float) totalModuleSize / 7.0f;
|
||||||
float maxVariance = moduleSize / 2.5f;
|
float maxVariance = moduleSize / 2.0f;
|
||||||
// Allow less than 40% variance from 1-1-3-1-1 proportions
|
// Allow less than 50% variance from 1-1-3-1-1 proportions
|
||||||
return Math.abs(moduleSize - stateCount[0]) < maxVariance &&
|
return Math.abs(moduleSize - stateCount[0]) < maxVariance &&
|
||||||
Math.abs(moduleSize - stateCount[1]) < maxVariance &&
|
Math.abs(moduleSize - stateCount[1]) < maxVariance &&
|
||||||
Math.abs(3.0f * moduleSize - stateCount[2]) < 3.0f * 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
|
* 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
|
* @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;
|
MonochromeBitmapSource image = this.image;
|
||||||
|
|
||||||
int maxI = image.getHeight();
|
int maxI = image.getHeight();
|
||||||
|
@ -254,15 +254,22 @@ final class FinderPatternFinder {
|
||||||
return Float.NaN;
|
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;
|
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
|
* 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>
|
* 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;
|
MonochromeBitmapSource image = this.image;
|
||||||
|
|
||||||
int maxJ = image.getWidth();
|
int maxJ = image.getWidth();
|
||||||
|
@ -314,6 +321,13 @@ final class FinderPatternFinder {
|
||||||
return Float.NaN;
|
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;
|
return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : Float.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,14 +350,14 @@ final class FinderPatternFinder {
|
||||||
private boolean handlePossibleCenter(int[] stateCount,
|
private boolean handlePossibleCenter(int[] stateCount,
|
||||||
int i,
|
int i,
|
||||||
int j) {
|
int j) {
|
||||||
|
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4];
|
||||||
float centerJ = centerFromEnd(stateCount, j);
|
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)) {
|
if (!Float.isNaN(centerI)) {
|
||||||
// Re-cross check
|
// Re-cross check
|
||||||
centerJ = crossCheckHorizontal((int) centerJ, (int) centerI, stateCount[2]);
|
centerJ = crossCheckHorizontal((int) centerJ, (int) centerI, stateCount[2], stateCountTotal);
|
||||||
if (!Float.isNaN(centerJ)) {
|
if (!Float.isNaN(centerJ)) {
|
||||||
float estimatedModuleSize =
|
float estimatedModuleSize = (float) stateCountTotal / 7.0f;
|
||||||
(float) (stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]) / 7.0f;
|
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
int max = possibleCenters.size();
|
int max = possibleCenters.size();
|
||||||
for (int index = 0; index < max; index++) {
|
for (int index = 0; index < max; index++) {
|
||||||
|
|
Loading…
Reference in a new issue