/** * Combines this object's current estimate of a finder pattern position and module size * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average * based on count. */ FinderPattern combineEstimate(float i, float j, float newModuleSize) { int combinedCount = count + 1; float combinedX = (count * getX() + j) / combinedCount; float combinedY = (count * getY() + i) / combinedCount; float combinedModuleSize = (count * estimatedModuleSize + newModuleSize) / combinedCount; return new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount); }
@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 ? -1 : 0; } else { return center2.getCount() - center1.getCount(); } } }
/** * <p>Determines if this finder pattern "about equals" a finder pattern at the stated * position and size -- meaning, it is at nearly the same center with nearly the same size.</p> */ boolean aboutEquals(float moduleSize, float i, float j) { if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) { float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize); return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize; } return false; }
for (int i = 0; i < max; i++) { FinderPattern center = (FinderPattern) possibleCenters.elementAt(i); if (center.getCount() >= CENTER_QUORUM) { if (firstConfirmedCenter == null) { firstConfirmedCenter = center; return (int) (Math.abs(firstConfirmedCenter.getX() - center.getX()) - Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2;
FinderPattern center = possibleCenters.get(index); if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { possibleCenters.set(index, center.combineEstimate(centerI, centerJ, estimatedModuleSize)); found = true; break; FinderPattern point = new FinderPattern(centerJ, centerI, estimatedModuleSize); possibleCenters.add(point); if (resultPointCallback != null) {
@Override public int compare(FinderPattern center1, FinderPattern center2) { float value = center2.getEstimatedModuleSize() - center1.getEstimatedModuleSize(); return value < 0.0 ? -1 : value > 0.0 ? 1 : 0; } }
FinderPattern center = (FinderPattern) possibleCenters.elementAt(index); if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { center.incrementCount(); found = true; break; ResultPoint point = new FinderPattern(centerJ, centerI, estimatedModuleSize); possibleCenters.addElement(point); if (resultPointCallback != null) {
/** * @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; } ResultPoint 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; }
/** * <p>Determines if this finder pattern "about equals" a finder pattern at the stated * position and size -- meaning, it is at nearly the same center with nearly the same size.</p> */ boolean aboutEquals(float moduleSize, float i, float j) { if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) { float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize); return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize; } return false; }
FinderPattern center = possibleCenters.get(index); if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) { possibleCenters.set(index, center.combineEstimate(centerI, centerJ, estimatedModuleSize)); found = true; break; FinderPattern point = new FinderPattern(centerJ, centerI, estimatedModuleSize); possibleCenters.add(point); if (resultPointCallback != null) {
@Override public int compare(FinderPattern center1, FinderPattern center2) { float value = center2.getEstimatedModuleSize() - center1.getEstimatedModuleSize(); return value < 0.0 ? -1 : value > 0.0 ? 1 : 0; } }
/** * @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; } ResultPoint 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; }
/** * <p>Determines if this finder pattern "about equals" a finder pattern at the stated * position and size -- meaning, it is at nearly the same center with nearly the same size.</p> */ boolean aboutEquals(float moduleSize, float i, float j) { if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) { float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize); return moduleSizeDiff <= 1.0f || moduleSizeDiff / estimatedModuleSize <= 1.0f; } return false; }
@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 ? -1 : 0; } else { return center2.getCount() - center1.getCount(); } } }
/** * Combines this object's current estimate of a finder pattern position and module size * with a new estimate. It returns a new {@code FinderPattern} containing a weighted average * based on count. */ FinderPattern combineEstimate(float i, float j, float newModuleSize) { int combinedCount = count + 1; float combinedX = (count * getX() + j) / combinedCount; float combinedY = (count * getY() + i) / combinedCount; float combinedModuleSize = (count * estimatedModuleSize + newModuleSize) / combinedCount; return new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount); }
public int compare(Object center1, Object center2) { float value = ((FinderPattern) center2).getEstimatedModuleSize() - ((FinderPattern) center1).getEstimatedModuleSize(); return value < 0.0 ? -1 : value > 0.0 ? 1 : 0; } }
float bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX(); float bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY(); int estAlignmentX = (int) (topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX())); int estAlignmentY = (int) (topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY()));
/** * @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 / 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) { float dA = Math.abs(center2.getEstimatedModuleSize() - average); float dB = Math.abs(center1.getEstimatedModuleSize() - average); return dA < dB ? -1 : dA > dB ? 1 : 0; } }