mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Improve detector logic to throw out false positive finder patterns in a more reasonable manner. Current logic didn't quite achieve its goal in some corner cases and needed rethinking and some simplification. Fixes a reported failure from the group list. Net change in passed test cases is -1 otherwise (for 270 degree rotation -- not vital) so I consider it a net tiny win.
git-svn-id: https://zxing.googlecode.com/svn/trunk@1039 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
362236564e
commit
e1dd41a115
|
@ -463,7 +463,7 @@ public class FinderPatternFinder {
|
||||||
// OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive"
|
// 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
|
// 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
|
// vary too much. We arbitrarily say that when the total deviation from average exceeds
|
||||||
// 15% of the total module size estimates, it's too much.
|
// 5% of the total module size estimates, it's too much.
|
||||||
float average = totalModuleSize / (float) max;
|
float average = totalModuleSize / (float) max;
|
||||||
float totalDeviation = 0.0f;
|
float totalDeviation = 0.0f;
|
||||||
for (int i = 0; i < max; i++) {
|
for (int i = 0; i < max; i++) {
|
||||||
|
@ -480,25 +480,35 @@ public class FinderPatternFinder {
|
||||||
* @throws ReaderException if 3 such finder patterns do not exist
|
* @throws ReaderException if 3 such finder patterns do not exist
|
||||||
*/
|
*/
|
||||||
private FinderPattern[] selectBestPatterns() throws ReaderException {
|
private FinderPattern[] selectBestPatterns() throws ReaderException {
|
||||||
if (possibleCenters.size() < 3) {
|
|
||||||
|
int startSize = possibleCenters.size();
|
||||||
|
if (startSize < 3) {
|
||||||
// Couldn't find enough finder patterns
|
// Couldn't find enough finder patterns
|
||||||
throw ReaderException.getInstance();
|
throw ReaderException.getInstance();
|
||||||
}
|
}
|
||||||
Collections.insertionSort(possibleCenters, new CenterComparator());
|
|
||||||
|
// 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;
|
||||||
|
for (int i = 0; i < startSize; i++) {
|
||||||
|
totalModuleSize += ((FinderPattern) possibleCenters.get(i)).getEstimatedModuleSize();
|
||||||
|
}
|
||||||
|
float average = totalModuleSize / (float) startSize;
|
||||||
|
for (int i = 0; i < possibleCenters.size() && possibleCenters.size() > 3; i++) {
|
||||||
|
FinderPattern pattern = (FinderPattern) possibleCenters.get(i);
|
||||||
|
if (Math.abs(pattern.getEstimatedModuleSize() - average) > 0.2f * average) {
|
||||||
|
possibleCenters.remove(i);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (possibleCenters.size() > 3) {
|
if (possibleCenters.size() > 3) {
|
||||||
// Throw away all but those first size candidate points we found.
|
// Throw away all but those first size candidate points we found.
|
||||||
|
Collections.insertionSort(possibleCenters, new CenterComparator());
|
||||||
possibleCenters.setSize(3);
|
possibleCenters.setSize(3);
|
||||||
}
|
}
|
||||||
// We need to pick the best three. Find the most
|
|
||||||
// popular ones whose module size is nearest the average
|
|
||||||
float averageModuleSize = 0.0f;
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
averageModuleSize += ((FinderPattern) possibleCenters.elementAt(i)).getEstimatedModuleSize();
|
|
||||||
}
|
|
||||||
averageModuleSize /= 3.0f;
|
|
||||||
// We don't have java.util.Collections in J2ME
|
|
||||||
Collections.insertionSort(possibleCenters, new ClosestToAverageComparator(averageModuleSize));
|
|
||||||
|
|
||||||
return new FinderPattern[]{
|
return new FinderPattern[]{
|
||||||
(FinderPattern) possibleCenters.elementAt(0),
|
(FinderPattern) possibleCenters.elementAt(0),
|
||||||
|
@ -516,22 +526,4 @@ public class FinderPatternFinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Orders by variance from average module size, ascending.</p>
|
|
||||||
*/
|
|
||||||
private static class ClosestToAverageComparator implements Comparator {
|
|
||||||
private final float averageModuleSize;
|
|
||||||
|
|
||||||
private ClosestToAverageComparator(float averageModuleSize) {
|
|
||||||
this.averageModuleSize = averageModuleSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int compare(Object center1, Object center2) {
|
|
||||||
return Math.abs(((FinderPattern) center1).getEstimatedModuleSize() - averageModuleSize) <
|
|
||||||
Math.abs(((FinderPattern) center2).getEstimatedModuleSize() - averageModuleSize) ?
|
|
||||||
-1 :
|
|
||||||
1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,9 @@ public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase {
|
||||||
public QRCodeBlackBox2TestCase() {
|
public QRCodeBlackBox2TestCase() {
|
||||||
super("test/data/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
super("test/data/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||||
addTest(23, 23, 0.0f);
|
addTest(23, 23, 0.0f);
|
||||||
addTest(20, 20, 90.0f);
|
addTest(21, 21, 90.0f);
|
||||||
addTest(21, 21, 180.0f);
|
addTest(20, 20, 180.0f);
|
||||||
addTest(19, 19, 270.0f);
|
addTest(18, 18, 270.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in a new issue