Detector.java (zxing-zxing-3.4.0) | : | Detector.java (zxing-zxing-3.4.1) | ||
---|---|---|---|---|
skipping to change at line 191 | skipping to change at line 191 | |||
private static ResultPoint[] findRowsWithPattern(BitMatrix matrix, | private static ResultPoint[] findRowsWithPattern(BitMatrix matrix, | |||
int height, | int height, | |||
int width, | int width, | |||
int startRow, | int startRow, | |||
int startColumn, | int startColumn, | |||
int[] pattern) { | int[] pattern) { | |||
ResultPoint[] result = new ResultPoint[4]; | ResultPoint[] result = new ResultPoint[4]; | |||
boolean found = false; | boolean found = false; | |||
int[] counters = new int[pattern.length]; | int[] counters = new int[pattern.length]; | |||
for (; startRow < height; startRow += ROW_STEP) { | for (; startRow < height; startRow += ROW_STEP) { | |||
int[] loc = findGuardPattern(matrix, startColumn, startRow, width, false, pattern, counters); | int[] loc = findGuardPattern(matrix, startColumn, startRow, width, pattern , counters); | |||
if (loc != null) { | if (loc != null) { | |||
while (startRow > 0) { | while (startRow > 0) { | |||
int[] previousRowLoc = findGuardPattern(matrix, startColumn, --startRo w, width, false, pattern, counters); | int[] previousRowLoc = findGuardPattern(matrix, startColumn, --startRo w, width, pattern, counters); | |||
if (previousRowLoc != null) { | if (previousRowLoc != null) { | |||
loc = previousRowLoc; | loc = previousRowLoc; | |||
} else { | } else { | |||
startRow++; | startRow++; | |||
break; | break; | |||
} | } | |||
} | } | |||
result[0] = new ResultPoint(loc[0], startRow); | result[0] = new ResultPoint(loc[0], startRow); | |||
result[1] = new ResultPoint(loc[1], startRow); | result[1] = new ResultPoint(loc[1], startRow); | |||
found = true; | found = true; | |||
break; | break; | |||
} | } | |||
} | } | |||
int stopRow = startRow + 1; | int stopRow = startRow + 1; | |||
// Last row of the current symbol that contains pattern | // Last row of the current symbol that contains pattern | |||
if (found) { | if (found) { | |||
int skippedRowCount = 0; | int skippedRowCount = 0; | |||
int[] previousRowLoc = {(int) result[0].getX(), (int) result[1].getX()}; | int[] previousRowLoc = {(int) result[0].getX(), (int) result[1].getX()}; | |||
for (; stopRow < height; stopRow++) { | for (; stopRow < height; stopRow++) { | |||
int[] loc = findGuardPattern(matrix, previousRowLoc[0], stopRow, width, false, pattern, counters); | int[] loc = findGuardPattern(matrix, previousRowLoc[0], stopRow, width, pattern, counters); | |||
// a found pattern is only considered to belong to the same barcode if t he start and end positions | // a found pattern is only considered to belong to the same barcode if t he start and end positions | |||
// don't differ too much. Pattern drift should be not bigger than two fo r consecutive rows. With | // don't differ too much. Pattern drift should be not bigger than two fo r consecutive rows. With | |||
// a higher number of skipped rows drift could be larger. To keep it sim ple for now, we allow a slightly | // a higher number of skipped rows drift could be larger. To keep it sim ple for now, we allow a slightly | |||
// larger drift and don't check for skipped rows. | // larger drift and don't check for skipped rows. | |||
if (loc != null && | if (loc != null && | |||
Math.abs(previousRowLoc[0] - loc[0]) < MAX_PATTERN_DRIFT && | Math.abs(previousRowLoc[0] - loc[0]) < MAX_PATTERN_DRIFT && | |||
Math.abs(previousRowLoc[1] - loc[1]) < MAX_PATTERN_DRIFT) { | Math.abs(previousRowLoc[1] - loc[1]) < MAX_PATTERN_DRIFT) { | |||
previousRowLoc = loc; | previousRowLoc = loc; | |||
skippedRowCount = 0; | skippedRowCount = 0; | |||
} else { | } else { | |||
skipping to change at line 256 | skipping to change at line 256 | |||
* @param width the number of pixels to search on this row | * @param width the number of pixels to search on this row | |||
* @param pattern pattern of counts of number of black and white pixels that a re | * @param pattern pattern of counts of number of black and white pixels that a re | |||
* being searched for as a pattern | * being searched for as a pattern | |||
* @param counters array of counters, as long as pattern, to re-use | * @param counters array of counters, as long as pattern, to re-use | |||
* @return start/end horizontal offset of guard pattern, as an array of two in ts. | * @return start/end horizontal offset of guard pattern, as an array of two in ts. | |||
*/ | */ | |||
private static int[] findGuardPattern(BitMatrix matrix, | private static int[] findGuardPattern(BitMatrix matrix, | |||
int column, | int column, | |||
int row, | int row, | |||
int width, | int width, | |||
boolean whiteFirst, | ||||
int[] pattern, | int[] pattern, | |||
int[] counters) { | int[] counters) { | |||
Arrays.fill(counters, 0, counters.length, 0); | Arrays.fill(counters, 0, counters.length, 0); | |||
int patternStart = column; | int patternStart = column; | |||
int pixelDrift = 0; | int pixelDrift = 0; | |||
// if there are black pixels left of the current pixel shift to the left, bu t only for MAX_PIXEL_DRIFT pixels | // if there are black pixels left of the current pixel shift to the left, bu t only for MAX_PIXEL_DRIFT pixels | |||
while (matrix.get(patternStart, row) && patternStart > 0 && pixelDrift++ < M AX_PIXEL_DRIFT) { | while (matrix.get(patternStart, row) && patternStart > 0 && pixelDrift++ < M AX_PIXEL_DRIFT) { | |||
patternStart--; | patternStart--; | |||
} | } | |||
int x = patternStart; | int x = patternStart; | |||
int counterPosition = 0; | int counterPosition = 0; | |||
int patternLength = pattern.length; | int patternLength = pattern.length; | |||
for (boolean isWhite = whiteFirst; x < width; x++) { | for (boolean isWhite = false; x < width; x++) { | |||
boolean pixel = matrix.get(x, row); | boolean pixel = matrix.get(x, row); | |||
if (pixel != isWhite) { | if (pixel != isWhite) { | |||
counters[counterPosition]++; | counters[counterPosition]++; | |||
} else { | } else { | |||
if (counterPosition == patternLength - 1) { | if (counterPosition == patternLength - 1) { | |||
if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) { | if (patternMatchVariance(counters, pattern) < MAX_AVG_VARIANCE) { | |||
return new int[] {patternStart, x}; | return new int[] {patternStart, x}; | |||
} | } | |||
patternStart += counters[0] + counters[1]; | patternStart += counters[0] + counters[1]; | |||
System.arraycopy(counters, 2, counters, 0, counterPosition - 1); | System.arraycopy(counters, 2, counters, 0, counterPosition - 1); | |||
counters[counterPosition - 1] = 0; | counters[counterPosition - 1] = 0; | |||
counters[counterPosition] = 0; | counters[counterPosition] = 0; | |||
counterPosition--; | counterPosition--; | |||
} else { | } else { | |||
counterPosition++; | counterPosition++; | |||
} | } | |||
counters[counterPosition] = 1; | counters[counterPosition] = 1; | |||
isWhite = !isWhite; | isWhite = !isWhite; | |||
} | } | |||
} | } | |||
if (counterPosition == patternLength - 1 && | if (counterPosition == patternLength - 1 && | |||
patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_A VG_VARIANCE) { | patternMatchVariance(counters, pattern) < MAX_AVG_VARIANCE) { | |||
return new int[] {patternStart, x - 1}; | return new int[] {patternStart, x - 1}; | |||
} | } | |||
return null; | return null; | |||
} | } | |||
/** | /** | |||
* Determines how closely a set of observed counts of runs of black/white | * Determines how closely a set of observed counts of runs of black/white | |||
* values matches a given target pattern. This is reported as the ratio of | * values matches a given target pattern. This is reported as the ratio of | |||
* the total variance from the expected pattern proportions across all | * the total variance from the expected pattern proportions across all | |||
* pattern elements, to the length of the pattern. | * pattern elements, to the length of the pattern. | |||
* | * | |||
* @param counters observed counters | * @param counters observed counters | |||
* @param pattern expected pattern | * @param pattern expected pattern | |||
* @param maxIndividualVariance The most any counter can differ before we give up | ||||
* @return ratio of total variance between counters and pattern compared to to tal pattern size | * @return ratio of total variance between counters and pattern compared to to tal pattern size | |||
*/ | */ | |||
private static float patternMatchVariance(int[] counters, int[] pattern, float maxIndividualVariance) { | private static float patternMatchVariance(int[] counters, int[] pattern) { | |||
int numCounters = counters.length; | int numCounters = counters.length; | |||
int total = 0; | int total = 0; | |||
int patternLength = 0; | int patternLength = 0; | |||
for (int i = 0; i < numCounters; i++) { | for (int i = 0; i < numCounters; i++) { | |||
total += counters[i]; | total += counters[i]; | |||
patternLength += pattern[i]; | patternLength += pattern[i]; | |||
} | } | |||
if (total < patternLength) { | if (total < patternLength) { | |||
// If we don't even have one pixel per unit of bar width, assume this | // If we don't even have one pixel per unit of bar width, assume this | |||
// is too small to reliably match, so fail: | // is too small to reliably match, so fail: | |||
return Float.POSITIVE_INFINITY; | return Float.POSITIVE_INFINITY; | |||
} | } | |||
// We're going to fake floating-point math in integers. We just need to use more bits. | // We're going to fake floating-point math in integers. We just need to use more bits. | |||
// Scale up patternLength so that intermediate values below like scaledCount er will have | // Scale up patternLength so that intermediate values below like scaledCount er will have | |||
// more "significant digits". | // more "significant digits". | |||
float unitBarWidth = (float) total / patternLength; | float unitBarWidth = (float) total / patternLength; | |||
maxIndividualVariance *= unitBarWidth; | float maxIndividualVariance = MAX_INDIVIDUAL_VARIANCE * unitBarWidth; | |||
float totalVariance = 0.0f; | float totalVariance = 0.0f; | |||
for (int x = 0; x < numCounters; x++) { | for (int x = 0; x < numCounters; x++) { | |||
int counter = counters[x]; | int counter = counters[x]; | |||
float scaledPattern = pattern[x] * unitBarWidth; | float scaledPattern = pattern[x] * unitBarWidth; | |||
float variance = counter > scaledPattern ? counter - scaledPattern : scale dPattern - counter; | float variance = counter > scaledPattern ? counter - scaledPattern : scale dPattern - counter; | |||
if (variance > maxIndividualVariance) { | if (variance > maxIndividualVariance) { | |||
return Float.POSITIVE_INFINITY; | return Float.POSITIVE_INFINITY; | |||
} | } | |||
totalVariance += variance; | totalVariance += variance; | |||
End of changes. 10 change blocks. | ||||
10 lines changed or deleted | 8 lines changed or added |