private int findRowSkip() { if (this.possibleCenters.size() <= 1) {} Object localObject; FinderPattern localFinderPattern; for (;;) { return 0; localObject = null; Iterator localIterator = this.possibleCenters.iterator(); while (localIterator.hasNext()) { localFinderPattern = (FinderPattern)localIterator.next(); if (localFinderPattern.getCount() >= 2) { if (localObject != null) { break label63; } localObject = localFinderPattern; } } } label63: this.hasSkipped = true; return (int)(Math.abs(localObject.getX() - localFinderPattern.getX()) - Math.abs(localObject.getY() - localFinderPattern.getY())) / 2; }
private boolean haveMultiplyConfirmedCenters() { int i = 0; float f1 = 0.0F; int j = this.possibleCenters.size(); Iterator localIterator1 = this.possibleCenters.iterator(); while (localIterator1.hasNext()) { FinderPattern localFinderPattern = (FinderPattern)localIterator1.next(); if (localFinderPattern.getCount() >= 2) { i++; f1 += localFinderPattern.getEstimatedModuleSize(); } } if (i < 3) {} float f3; do { return false; float f2 = f1 / j; f3 = 0.0F; Iterator localIterator2 = this.possibleCenters.iterator(); while (localIterator2.hasNext()) { f3 += Math.abs(((FinderPattern)localIterator2.next()).getEstimatedModuleSize() - f2); } } while (f3 > 0.05F * f1); return true; }
/** * This is called when a horizontal scan finds a possible alignment pattern. It will cross check * with a vertical scan, and if successful, will, ah, cross-cross-check with another horizontal * scan. This is needed primarily to locate the real horizontal center of the pattern in cases of * extreme skew. * * <p>If that succeeds the finder pattern location is added to a list that tracks the number of * times each location has been nearly-matched as a finder pattern. Each additional find is more * evidence that the location is in fact a finder pattern center * * @param stateCount reading state module counts from horizontal scan * @param i row where finder pattern may be found * @param j end of possible finder pattern in row * @return true if a finder pattern candidate was found this time */ protected final 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], stateCountTotal); if (!Float.isNaN(centerI)) { // Re-cross check centerJ = crossCheckHorizontal((int) centerJ, (int) centerI, stateCount[2], stateCountTotal); if (!Float.isNaN(centerJ)) { float estimatedModuleSize = (float) stateCountTotal / 7.0f; boolean found = false; for (int index = 0; index < possibleCenters.size(); index++) { FinderPattern center = possibleCenters.get(index); // Look for about the same center and module size: if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { possibleCenters.set( index, center.combineEstimate(centerI, centerJ, estimatedModuleSize)); found = true; break; } } if (!found) { FinderPattern point = new FinderPattern(centerJ, centerI, estimatedModuleSize); possibleCenters.add(point); if (resultPointCallback != null) { resultPointCallback.foundPossibleResultPoint(point); } } return true; } } return false; }
public int compare(FinderPattern paramFinderPattern1, FinderPattern paramFinderPattern2) { float f1 = Math.abs(paramFinderPattern2.getEstimatedModuleSize() - this.average); float f2 = Math.abs(paramFinderPattern1.getEstimatedModuleSize() - this.average); if (f1 < f2) { return -1; } if (f1 == f2) { return 0; } return 1; }
/** * @return number of rows we could safely skip during scanning, based on the first two finder * patterns that have been located. In some cases their position will allow us to infer that * the third pattern must lie below a certain point farther down in the image. */ private int findRowSkip() { int max = possibleCenters.size(); if (max <= 1) { return 0; } FinderPattern firstConfirmedCenter = null; for (FinderPattern center : possibleCenters) { if (center.getCount() >= CENTER_QUORUM) { if (firstConfirmedCenter == null) { firstConfirmedCenter = center; } else { // We have two confirmed centers // How far down can we skip before resuming looking for the next // pattern? In the worst case, only the difference between the // difference in the x / y coordinates of the two centers. // This is the case where you find top left last. hasSkipped = true; return (int) (Math.abs(firstConfirmedCenter.getX() - center.getX()) - Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2; } } } return 0; }
protected final boolean handlePossibleCenter(int[] paramArrayOfInt, int paramInt1, int paramInt2) { int i = paramArrayOfInt[0] + paramArrayOfInt[1] + paramArrayOfInt[2] + paramArrayOfInt[3] + paramArrayOfInt[4]; float f1 = centerFromEnd(paramArrayOfInt, paramInt2); float f2 = crossCheckVertical(paramInt1, (int)f1, paramArrayOfInt[2], i); if (!Float.isNaN(f2)) { float f3 = crossCheckHorizontal((int)f1, (int)f2, paramArrayOfInt[2], i); if (!Float.isNaN(f3)) { float f4 = i / 7.0F; for (int j = 0;; j++) { int k = this.possibleCenters.size(); int m = 0; if (j < k) { FinderPattern localFinderPattern2 = (FinderPattern)this.possibleCenters.get(j); if (localFinderPattern2.aboutEquals(f4, f2, f3)) { this.possibleCenters.set(j, localFinderPattern2.combineEstimate(f2, f3, f4)); m = 1; } } else { if (m == 0) { FinderPattern localFinderPattern1 = new FinderPattern(f3, f2, f4); this.possibleCenters.add(localFinderPattern1); if (this.resultPointCallback != null) { this.resultPointCallback.foundPossibleResultPoint(localFinderPattern1); } } return true; } } } } return false; }
/** * @return true iff we have found at least 3 finder patterns that have been detected at least * {@link #CENTER_QUORUM} times each, and, the estimated module size of the candidates is * "pretty similar" */ private boolean haveMultiplyConfirmedCenters() { int confirmedCount = 0; float totalModuleSize = 0.0f; int max = possibleCenters.size(); for (FinderPattern pattern : possibleCenters) { if (pattern.getCount() >= CENTER_QUORUM) { confirmedCount++; totalModuleSize += pattern.getEstimatedModuleSize(); } } if (confirmedCount < 3) { return false; } // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive" // and that we need to keep looking. We detect this by asking if the estimated module sizes // vary too much. We arbitrarily say that when the total deviation from average exceeds // 5% of the total module size estimates, it's too much. float average = totalModuleSize / (float) max; float totalDeviation = 0.0f; for (FinderPattern pattern : possibleCenters) { totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average); } return totalDeviation <= 0.05f * totalModuleSize; }
@Override public int compare(FinderPattern center1, FinderPattern center2) { if (center2.getCount() == center1.getCount()) { float dA = Math.abs(center2.getEstimatedModuleSize() - average); float dB = Math.abs(center1.getEstimatedModuleSize() - average); return dA < dB ? 1 : dA == dB ? 0 : -1; } else { return center2.getCount() - center1.getCount(); } }
/** * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are those * that have been detected at least {@link #CENTER_QUORUM} times, and whose module size * differs from the average among those patterns the least * @throws NotFoundException if 3 such finder patterns do not exist */ private FinderPattern[] selectBestPatterns() throws NotFoundException { int startSize = possibleCenters.size(); if (startSize < 3) { // Couldn't find enough finder patterns throw NotFoundException.getNotFoundInstance(); } // Filter outlier possibilities whose module size is too different if (startSize > 3) { // But we can only afford to do so if we have at least 4 possibilities to choose from float totalModuleSize = 0.0f; float square = 0.0f; for (FinderPattern center : possibleCenters) { float size = center.getEstimatedModuleSize(); totalModuleSize += size; square += size * size; } float average = totalModuleSize / (float) startSize; float stdDev = (float) Math.sqrt(square / startSize - average * average); Collections.sort(possibleCenters, new FurthestFromAverageComparator(average)); float limit = Math.max(0.2f * average, stdDev); for (int i = 0; i < possibleCenters.size() && possibleCenters.size() > 3; i++) { FinderPattern pattern = possibleCenters.get(i); if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) { possibleCenters.remove(i); i--; } } } if (possibleCenters.size() > 3) { // Throw away all but those first size candidate points we found. float totalModuleSize = 0.0f; for (FinderPattern possibleCenter : possibleCenters) { totalModuleSize += possibleCenter.getEstimatedModuleSize(); } float average = totalModuleSize / (float) possibleCenters.size(); Collections.sort(possibleCenters, new CenterComparator(average)); possibleCenters.subList(3, possibleCenters.size()).clear(); } return new FinderPattern[] { possibleCenters.get(0), possibleCenters.get(1), possibleCenters.get(2) }; }
protected final DetectorResult a(FinderPatternInfo paramFinderPatternInfo) { FinderPattern localFinderPattern1 = paramFinderPatternInfo.b(); FinderPattern localFinderPattern2 = paramFinderPatternInfo.c(); FinderPattern localFinderPattern3 = paramFinderPatternInfo.a(); float f1 = a(localFinderPattern1, localFinderPattern2, localFinderPattern3); if (f1 < 1.0F) throw NotFoundException.a(); int i = a(localFinderPattern1, localFinderPattern2, localFinderPattern3, f1); Version localVersion = Version.a(i); int j = -7 + localVersion.d(); int k = localVersion.b().length; Object localObject = null; int m; int n; int i1; float f5; if (k > 0) { float f2 = localFinderPattern2.a() - localFinderPattern1.a() + localFinderPattern3.a(); float f3 = localFinderPattern2.b() - localFinderPattern1.b() + localFinderPattern3.b(); float f4 = 1.0F - 3.0F / j; m = (int)(localFinderPattern1.a() + f4 * (f2 - localFinderPattern1.a())); n = (int)(localFinderPattern1.b() + f4 * (f3 - localFinderPattern1.b())); i1 = 4; localObject = null; if (i1 <= 16) f5 = i1; } while (true) { try { AlignmentPattern localAlignmentPattern = a(f1, m, n, f5); localObject = localAlignmentPattern; PerspectiveTransform localPerspectiveTransform = a(localFinderPattern1, localFinderPattern2, localFinderPattern3, localObject, i); BitMatrix localBitMatrix = a(this.a, localPerspectiveTransform, i); if (localObject != null) break label270; arrayOfResultPoint = new ResultPoint[] { localFinderPattern3, localFinderPattern1, localFinderPattern2 }; return new DetectorResult(localBitMatrix, arrayOfResultPoint); } catch (NotFoundException localNotFoundException) { i1 <<= 1; } break; label270: ResultPoint[] arrayOfResultPoint = { localFinderPattern3, localFinderPattern1, localFinderPattern2, localObject }; } }
@Override public int compare(FinderPattern center1, FinderPattern center2) { float dA = Math.abs(center2.getEstimatedModuleSize() - average); float dB = Math.abs(center1.getEstimatedModuleSize() - average); return dA < dB ? -1 : dA == dB ? 0 : 1; }