mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Detect RSS Expanded finder pattern false positives by checking sequences (#1680)
This commit is contained in:
parent
b79a70bb33
commit
60ae2ed949
|
@ -29,7 +29,9 @@ public abstract class AbstractRSSReader extends OneDReader {
|
||||||
private static final float MAX_AVG_VARIANCE = 0.2f;
|
private static final float MAX_AVG_VARIANCE = 0.2f;
|
||||||
private static final float MAX_INDIVIDUAL_VARIANCE = 0.45f;
|
private static final float MAX_INDIVIDUAL_VARIANCE = 0.45f;
|
||||||
|
|
||||||
|
/** Minimum ratio 10:12 (minus 0.5 for variance), from section 7.2.7 of ISO/IEC 24724:2006. */
|
||||||
private static final float MIN_FINDER_PATTERN_RATIO = 9.5f / 12.0f;
|
private static final float MIN_FINDER_PATTERN_RATIO = 9.5f / 12.0f;
|
||||||
|
/** Maximum ratio 12:14 (plus 0.5 for variance), from section 7.2.7 of ISO/IEC 24724:2006. */
|
||||||
private static final float MAX_FINDER_PATTERN_RATIO = 12.5f / 14.0f;
|
private static final float MAX_FINDER_PATTERN_RATIO = 12.5f / 14.0f;
|
||||||
|
|
||||||
private final int[] decodeFinderCounters;
|
private final int[] decodeFinderCounters;
|
||||||
|
|
|
@ -59,6 +59,7 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
private static final int[] EVEN_TOTAL_SUBSET = {4, 20, 52, 104, 204};
|
private static final int[] EVEN_TOTAL_SUBSET = {4, 20, 52, 104, 204};
|
||||||
private static final int[] GSUM = {0, 348, 1388, 2948, 3988};
|
private static final int[] GSUM = {0, 348, 1388, 2948, 3988};
|
||||||
|
|
||||||
|
/** Finder pattern element widths, from section 7.2.7 of ISO/IEC 24724:2006. */
|
||||||
private static final int[][] FINDER_PATTERNS = {
|
private static final int[][] FINDER_PATTERNS = {
|
||||||
{1,8,4,1}, // A
|
{1,8,4,1}, // A
|
||||||
{3,6,4,1}, // B
|
{3,6,4,1}, // B
|
||||||
|
@ -68,6 +69,7 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
{2,2,9,1} // F
|
{2,2,9,1} // F
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** The element weights used in the checksum calculation, from section 7.2.6 of ISO/IEC 24724:2006. */
|
||||||
private static final int[][] WEIGHTS = {
|
private static final int[][] WEIGHTS = {
|
||||||
{ 1, 3, 9, 27, 81, 32, 96, 77},
|
{ 1, 3, 9, 27, 81, 32, 96, 77},
|
||||||
{ 20, 60, 180, 118, 143, 7, 21, 63},
|
{ 20, 60, 180, 118, 143, 7, 21, 63},
|
||||||
|
@ -101,6 +103,7 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
private static final int FINDER_PAT_E = 4;
|
private static final int FINDER_PAT_E = 4;
|
||||||
private static final int FINDER_PAT_F = 5;
|
private static final int FINDER_PAT_F = 5;
|
||||||
|
|
||||||
|
/** The possible finder pattern sequences, from section 7.2.7 of ISO/IEC 24724:2006. */
|
||||||
@SuppressWarnings("checkstyle:lineLength")
|
@SuppressWarnings("checkstyle:lineLength")
|
||||||
private static final int[][] FINDER_PATTERN_SEQUENCES = {
|
private static final int[][] FINDER_PATTERN_SEQUENCES = {
|
||||||
{ FINDER_PAT_A, FINDER_PAT_A },
|
{ FINDER_PAT_A, FINDER_PAT_A },
|
||||||
|
@ -243,9 +246,9 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
throw NotFoundException.getNotFoundInstance();
|
throw NotFoundException.getNotFoundInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Whether the pairs form a valid find pattern sequence,
|
// Whether the pairs form a valid finder pattern sequence, either complete or a prefix
|
||||||
// either complete or a prefix
|
|
||||||
private static boolean isValidSequence(List<ExpandedPair> pairs) {
|
private static boolean isValidSequence(List<ExpandedPair> pairs) {
|
||||||
|
|
||||||
for (int[] sequence : FINDER_PATTERN_SEQUENCES) {
|
for (int[] sequence : FINDER_PATTERN_SEQUENCES) {
|
||||||
if (pairs.size() <= sequence.length) {
|
if (pairs.size() <= sequence.length) {
|
||||||
boolean stop = true;
|
boolean stop = true;
|
||||||
|
@ -259,12 +262,47 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether the pairs, plus another pair of the specified type, would together
|
||||||
|
// form a valid finder pattern sequence, either complete or partial
|
||||||
|
private static boolean mayFollow(List<ExpandedPair> pairs, int value) {
|
||||||
|
|
||||||
|
if (pairs.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int[] sequence : FINDER_PATTERN_SEQUENCES) {
|
||||||
|
if (pairs.size() + 1 <= sequence.length) {
|
||||||
|
// the proposed sequence (i.e. pairs + value) would fit in this allowed sequence
|
||||||
|
for (int i = pairs.size(); i < sequence.length; i++) {
|
||||||
|
if (sequence[i] == value) {
|
||||||
|
// we found our value in this allowed sequence, check to see if the elements preceding it match our existing
|
||||||
|
// pairs; note our existing pairs may not be a full sequence (e.g. if processing a row in a stacked symbol)
|
||||||
|
boolean matched = true;
|
||||||
|
for (int j = 0; j < pairs.size(); j++) {
|
||||||
|
int allowed = sequence[i - j - 1];
|
||||||
|
int actual = pairs.get(pairs.size() - j - 1).getFinderPattern().getValue();
|
||||||
|
if (allowed != actual) {
|
||||||
|
matched = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (matched) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the proposed finder pattern sequence is illegal
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private void storeRow(int rowNumber) {
|
private void storeRow(int rowNumber) {
|
||||||
// Discard if duplicate above or below; otherwise insert in order by row number.
|
// Discard if duplicate above or below; otherwise insert in order by row number.
|
||||||
int insertPos = 0;
|
int insertPos = 0;
|
||||||
|
@ -423,7 +461,7 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
int forcedOffset = -1;
|
int forcedOffset = -1;
|
||||||
do {
|
do {
|
||||||
this.findNextPair(row, previousPairs, forcedOffset);
|
this.findNextPair(row, previousPairs, forcedOffset);
|
||||||
pattern = parseFoundFinderPattern(row, rowNumber, isOddPattern);
|
pattern = parseFoundFinderPattern(row, rowNumber, isOddPattern, previousPairs);
|
||||||
if (pattern == null) {
|
if (pattern == null) {
|
||||||
forcedOffset = getNextSecondBar(row, this.startEnd[0]);
|
forcedOffset = getNextSecondBar(row, this.startEnd[0]);
|
||||||
} else {
|
} else {
|
||||||
|
@ -528,7 +566,10 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private FinderPattern parseFoundFinderPattern(BitArray row, int rowNumber, boolean oddPattern) {
|
private FinderPattern parseFoundFinderPattern(BitArray row,
|
||||||
|
int rowNumber,
|
||||||
|
boolean oddPattern,
|
||||||
|
List<ExpandedPair> previousPairs) {
|
||||||
// Actually we found elements 2-5.
|
// Actually we found elements 2-5.
|
||||||
int firstCounter;
|
int firstCounter;
|
||||||
int start;
|
int start;
|
||||||
|
@ -568,6 +609,12 @@ public final class RSSExpandedReader extends AbstractRSSReader {
|
||||||
} catch (NotFoundException ignored) {
|
} catch (NotFoundException ignored) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the pattern type that we *think* we found can exist as part of a valid sequence of finder patterns.
|
||||||
|
if (!mayFollow(previousPairs, value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return new FinderPattern(value, new int[] {start, end}, start, end, rowNumber);
|
return new FinderPattern(value, new int[] {start, end}, start, end, rowNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ public final class RSSExpandedBlackBox1TestCase extends AbstractBlackBoxTestCase
|
||||||
|
|
||||||
public RSSExpandedBlackBox1TestCase() {
|
public RSSExpandedBlackBox1TestCase() {
|
||||||
super("src/test/resources/blackbox/rssexpanded-1", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED);
|
super("src/test/resources/blackbox/rssexpanded-1", new MultiFormatReader(), BarcodeFormat.RSS_EXPANDED);
|
||||||
addTest(32, 32, 0.0f);
|
addTest(33, 33, 0.0f);
|
||||||
addTest(32, 32, 180.0f);
|
addTest(33, 33, 180.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
BIN
core/src/test/resources/blackbox/rssexpanded-1/33.png
Normal file
BIN
core/src/test/resources/blackbox/rssexpanded-1/33.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
1
core/src/test/resources/blackbox/rssexpanded-1/33.txt
Normal file
1
core/src/test/resources/blackbox/rssexpanded-1/33.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
(420)azaaaaa"agaa&a3
|
Loading…
Reference in a new issue