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 |