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
|
Suraj Supekar
|
||||||
Sven Klinkhamer
|
Sven Klinkhamer
|
||||||
Thomas Gerbet
|
Thomas Gerbet
|
||||||
|
Tim Gernat
|
||||||
v.anestis
|
v.anestis
|
||||||
Vince Francis (LifeMarks)
|
Vince Francis (LifeMarks)
|
||||||
Wolfgang Jung
|
Wolfgang Jung
|
||||||
|
|
|
@ -40,9 +40,20 @@ public final class AlignmentPattern extends ResultPoint {
|
||||||
boolean aboutEquals(float moduleSize, float i, float j) {
|
boolean aboutEquals(float moduleSize, float i, float j) {
|
||||||
if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
|
if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
|
||||||
float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
|
float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
|
||||||
return moduleSizeDiff <= 1.0f || moduleSizeDiff / estimatedModuleSize <= 1.0f;
|
return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize;
|
||||||
}
|
}
|
||||||
return false;
|
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);
|
AlignmentPattern center = (AlignmentPattern) possibleCenters.elementAt(index);
|
||||||
// Look for about the same center and module size:
|
// Look for about the same center and module size:
|
||||||
if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
|
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
|
// Hadn't found this before; save it
|
||||||
|
|
|
@ -31,9 +31,13 @@ public final class FinderPattern extends ResultPoint {
|
||||||
private int count;
|
private int count;
|
||||||
|
|
||||||
FinderPattern(float posX, float posY, float estimatedModuleSize) {
|
FinderPattern(float posX, float posY, float estimatedModuleSize) {
|
||||||
|
this(posX, posY, estimatedModuleSize, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
FinderPattern(float posX, float posY, float estimatedModuleSize, int count) {
|
||||||
super(posX, posY);
|
super(posX, posY);
|
||||||
this.estimatedModuleSize = estimatedModuleSize;
|
this.estimatedModuleSize = estimatedModuleSize;
|
||||||
this.count = 1;
|
this.count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getEstimatedModuleSize() {
|
public float getEstimatedModuleSize() {
|
||||||
|
@ -55,9 +59,22 @@ public final class FinderPattern extends ResultPoint {
|
||||||
boolean aboutEquals(float moduleSize, float i, float j) {
|
boolean aboutEquals(float moduleSize, float i, float j) {
|
||||||
if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
|
if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
|
||||||
float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
|
float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
|
||||||
return moduleSizeDiff <= 1.0f || moduleSizeDiff / estimatedModuleSize <= 1.0f;
|
return moduleSizeDiff <= 1.0f || moduleSizeDiff <= estimatedModuleSize;
|
||||||
}
|
}
|
||||||
return false;
|
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);
|
FinderPattern center = (FinderPattern) possibleCenters.elementAt(index);
|
||||||
// Look for about the same center and module size:
|
// Look for about the same center and module size:
|
||||||
if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
|
if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
|
||||||
center.incrementCount();
|
possibleCenters.setElementAt(center.combineEstimate(centerI, centerJ, estimatedModuleSize), index);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
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() {
|
public QRCodeBlackBox4TestCase() {
|
||||||
super("test/data/blackbox/qrcode-4", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
super("test/data/blackbox/qrcode-4", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||||
addTest(36, 36, 0.0f);
|
addTest(36, 36, 0.0f);
|
||||||
addTest(36, 36, 90.0f);
|
addTest(35, 35, 90.0f);
|
||||||
addTest(35, 35, 180.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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|