Improvement to finder/alignment pattern detection in low-res situations: use averages. It makes it much better on images of this sort, decreasing failure rate by about 60%. (It makes one old image fail, but looks like a fluke)
git-svn-id: https://zxing.googlecode.com/svn/trunk@1875 59b500cc-1b3d-0410-9834-0bbf25fbcc57
1
AUTHORS
|
@ -68,6 +68,7 @@ Steven Parkes
|
|||
Suraj Supekar
|
||||
Sven Klinkhamer
|
||||
Thomas Gerbet
|
||||
Tim Gernat
|
||||
v.anestis
|
||||
Vince Francis (LifeMarks)
|
||||
Wolfgang Jung
|
||||
|
|
|
@ -40,9 +40,20 @@ public final class AlignmentPattern extends ResultPoint {
|
|||
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 moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 an average of the two.
|
||||
*/
|
||||
AlignmentPattern combineEstimate(float i, float j, float newModuleSize) {
|
||||
float combinedX = (getX() + j) / 2.0f;
|
||||
float combinedY = (getY() + i) / 2.0f;
|
||||
float combinedModuleSize = (estimatedModuleSize + newModuleSize) / 2.0f;
|
||||
return new AlignmentPattern(combinedX, combinedY, combinedModuleSize);
|
||||
}
|
||||
|
||||
}
|
|
@ -263,7 +263,7 @@ final class AlignmentPatternFinder {
|
|||
AlignmentPattern center = (AlignmentPattern) possibleCenters.elementAt(index);
|
||||
// Look for about the same center and module size:
|
||||
if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
|
||||
return new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
|
||||
return center.combineEstimate(centerI, centerJ, estimatedModuleSize);
|
||||
}
|
||||
}
|
||||
// Hadn't found this before; save it
|
||||
|
|
|
@ -31,9 +31,13 @@ public final class FinderPattern extends ResultPoint {
|
|||
private int count;
|
||||
|
||||
FinderPattern(float posX, float posY, float estimatedModuleSize) {
|
||||
this(posX, posY, estimatedModuleSize, 1);
|
||||
}
|
||||
|
||||
FinderPattern(float posX, float posY, float estimatedModuleSize, int count) {
|
||||
super(posX, posY);
|
||||
this.estimatedModuleSize = estimatedModuleSize;
|
||||
this.count = 1;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public float getEstimatedModuleSize() {
|
||||
|
@ -55,9 +59,22 @@ public final class FinderPattern extends ResultPoint {
|
|||
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 moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 * getEstimatedModuleSize() + newModuleSize) / combinedCount;
|
||||
return new FinderPattern(combinedX, combinedY, combinedModuleSize, combinedCount);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -404,7 +404,7 @@ public class FinderPatternFinder {
|
|||
FinderPattern center = (FinderPattern) possibleCenters.elementAt(index);
|
||||
// Look for about the same center and module size:
|
||||
if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
|
||||
center.incrementCount();
|
||||
possibleCenters.setElementAt(center.combineEstimate(centerI, centerJ, estimatedModuleSize), index);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
BIN
core/test/data/blackbox/qrcode-6/1.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/1.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/10.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/10.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/11.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/11.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/12.png
Executable file
After Width: | Height: | Size: 2.6 KiB |
1
core/test/data/blackbox/qrcode-6/12.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/13.png
Executable file
After Width: | Height: | Size: 2.6 KiB |
1
core/test/data/blackbox/qrcode-6/13.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/14.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/14.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/2.png
Executable file
After Width: | Height: | Size: 2.6 KiB |
1
core/test/data/blackbox/qrcode-6/2.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/3.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/3.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/4.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/4.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/5.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/5.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/6.png
Executable file
After Width: | Height: | Size: 2.9 KiB |
1
core/test/data/blackbox/qrcode-6/6.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/7.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/7.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/8.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/8.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
BIN
core/test/data/blackbox/qrcode-6/9.png
Executable file
After Width: | Height: | Size: 2.5 KiB |
1
core/test/data/blackbox/qrcode-6/9.txt
Normal file
|
@ -0,0 +1 @@
|
|||
1234567890
|
|
@ -30,9 +30,9 @@ public final class QRCodeBlackBox4TestCase extends AbstractBlackBoxTestCase {
|
|||
public QRCodeBlackBox4TestCase() {
|
||||
super("test/data/blackbox/qrcode-4", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
addTest(36, 36, 0.0f);
|
||||
addTest(36, 36, 90.0f);
|
||||
addTest(35, 35, 90.0f);
|
||||
addTest(35, 35, 180.0f);
|
||||
addTest(35, 35, 270.0f);
|
||||
addTest(34, 34, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.zxing.qrcode;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.common.AbstractBlackBoxTestCase;
|
||||
|
||||
/**
|
||||
* These tests are supplied by Tim Gernat and test finder pattern detection at small size and under
|
||||
* rotation, which was a weak spot.
|
||||
*/
|
||||
public final class QRCodeBlackBox6TestCase extends AbstractBlackBoxTestCase {
|
||||
|
||||
public QRCodeBlackBox6TestCase() {
|
||||
super("test/data/blackbox/qrcode-6", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
addTest(14, 14, 0.0f);
|
||||
addTest(13, 13, 90.0f);
|
||||
addTest(11, 12, 180.0f);
|
||||
addTest(13, 13, 270.0f);
|
||||
}
|
||||
|
||||
}
|