mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
Tweak blackpoints estimates for internal black blocks. Closes Issue 1012.
git-svn-id: https://zxing.googlecode.com/svn/trunk@1973 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
69988df528
commit
70190f7805
|
@ -1,3 +1,4 @@
|
|||
// -*- mode:java; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||
/*
|
||||
* Copyright 2009 ZXing authors
|
||||
*
|
||||
|
@ -132,13 +133,21 @@ public final class HybridBinarizer extends GlobalHistogramBinarizer {
|
|||
BitMatrix matrix) {
|
||||
for (int y = 0, offset = yoffset * stride + xoffset; y < BLOCK_SIZE; y++, offset += stride) {
|
||||
for (int x = 0; x < BLOCK_SIZE; x++) {
|
||||
if ((luminances[offset + x] & 0xFF) < threshold) {
|
||||
// Comparison needs to be <= so that black == 0 pixels are black even if the threshold is 0
|
||||
if ((luminances[offset + x] & 0xFF) <= threshold) {
|
||||
matrix.set(xoffset + x, yoffset + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Esimates blackPoint from previously calculated neighbor esitmates
|
||||
private static int getBlackPointFromNeighbors(int[][] blackPoints, int x, int y) {
|
||||
return (blackPoints[y-1][x] +
|
||||
2*blackPoints[y][x-1] +
|
||||
blackPoints[y-1][x-1]) >> 2;
|
||||
}
|
||||
|
||||
// Calculates a single black point for each 8x8 block of pixels and saves it away.
|
||||
private static int[][] calculateBlackPoints(byte[] luminances,
|
||||
int subWidth,
|
||||
|
@ -172,15 +181,38 @@ public final class HybridBinarizer extends GlobalHistogramBinarizer {
|
|||
}
|
||||
}
|
||||
|
||||
// If the contrast is inadequate, use half the minimum, so that this block will be
|
||||
// treated as part of the white background, but won't drag down neighboring blocks
|
||||
// too much.
|
||||
int average;
|
||||
if (max - min > 24) {
|
||||
average = sum >> 6;
|
||||
} else {
|
||||
// When min == max == 0, let average be 1 so all is black
|
||||
average = max == 0 ? 1 : min >> 1;
|
||||
// See
|
||||
// http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
|
||||
|
||||
// The default estimate is the average of the values in the block
|
||||
int average = sum >> 6;
|
||||
|
||||
if (max - min <= 24) {
|
||||
// If variation wihthin the block is low, assume this is a
|
||||
// block with only light or only dark pixels.
|
||||
|
||||
// The default assumption is that the block is light/background.
|
||||
// Since no estimate for the level of dark pixels
|
||||
// exists locally, use half the min for the block.
|
||||
average = min >> 1;
|
||||
|
||||
if (y > 0 && x > 0) {
|
||||
// Correct the "white/background" assumption for blocks
|
||||
// that have neighbors by comparing the pixels in this
|
||||
// block to the previously calculated blackpoints. This is
|
||||
// based on the fact that dark barcode symbology is always
|
||||
// surrounded by some amount of light background for which
|
||||
// reasonable blackpoint esimates were made. The bp estimated
|
||||
// at the bondaries is used for the interior.
|
||||
|
||||
// The (min < bp) seems pretty arbitrary but works better than
|
||||
// other heurstics that were tried.
|
||||
|
||||
int bp = getBlackPointFromNeighbors(blackPoints, x, y);
|
||||
if (min < bp) {
|
||||
average = bp;
|
||||
}
|
||||
}
|
||||
}
|
||||
blackPoints[y][x] = average;
|
||||
}
|
||||
|
|
BIN
core/test/data/blackbox/qrcode-6/15.jpg
Normal file
BIN
core/test/data/blackbox/qrcode-6/15.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 321 KiB |
1
core/test/data/blackbox/qrcode-6/15.txt
Normal file
1
core/test/data/blackbox/qrcode-6/15.txt
Normal file
|
@ -0,0 +1 @@
|
|||
TEST
|
|
@ -29,7 +29,7 @@ public final class AztecBlackBox2TestCase extends AbstractBlackBoxTestCase {
|
|||
public AztecBlackBox2TestCase() {
|
||||
super("test/data/blackbox/aztec-2", new AztecReader(), BarcodeFormat.AZTEC);
|
||||
addTest(2, 2, 0.0f);
|
||||
addTest(2, 2, 90.0f);
|
||||
addTest(1, 1, 90.0f);
|
||||
addTest(3, 3, 180.0f);
|
||||
addTest(1, 1, 270.0f);
|
||||
}
|
||||
|
|
|
@ -27,10 +27,10 @@ public final class DataMatrixBlackBox2TestCase extends AbstractBlackBoxTestCase
|
|||
|
||||
public DataMatrixBlackBox2TestCase() {
|
||||
super("test/data/blackbox/datamatrix-2", new MultiFormatReader(), BarcodeFormat.DATA_MATRIX);
|
||||
addTest(10, 10, 0.0f);
|
||||
addTest(13, 13, 90.0f);
|
||||
addTest(16, 16, 180.0f);
|
||||
addTest(13, 13, 270.0f);
|
||||
addTest(8, 8, 0.0f);
|
||||
addTest(14, 14, 90.0f);
|
||||
addTest(14, 14, 180.0f);
|
||||
addTest(12, 12, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,8 +33,8 @@ public final class PDF417BlackBox2TestCase extends AbstractBlackBoxTestCase {
|
|||
|
||||
public PDF417BlackBox2TestCase() {
|
||||
super("test/data/blackbox/pdf417-2", new MultiFormatReader(), BarcodeFormat.PDF_417);
|
||||
addTest(13, 13, 0.0f);
|
||||
addTest(13, 13, 180.0f);
|
||||
addTest(15, 15, 0.0f);
|
||||
addTest(14, 14, 180.0f);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -28,8 +28,8 @@ public final class QRCodeBlackBox1TestCase extends AbstractBlackBoxTestCase {
|
|||
public QRCodeBlackBox1TestCase() {
|
||||
super("test/data/blackbox/qrcode-1", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
addTest(17, 17, 0.0f);
|
||||
addTest(13, 13, 90.0f);
|
||||
addTest(16, 16, 180.0f);
|
||||
addTest(14, 14, 90.0f);
|
||||
addTest(17, 17, 180.0f);
|
||||
addTest(14, 14, 270.0f);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,10 @@ public final class QRCodeBlackBox2TestCase extends AbstractBlackBoxTestCase {
|
|||
|
||||
public QRCodeBlackBox2TestCase() {
|
||||
super("test/data/blackbox/qrcode-2", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
addTest(29, 29, 0.0f);
|
||||
addTest(29, 29, 90.0f);
|
||||
addTest(29, 29, 180.0f);
|
||||
addTest(28, 28, 270.0f);
|
||||
addTest(30, 30, 0.0f);
|
||||
addTest(30, 30, 90.0f);
|
||||
addTest(30, 30, 180.0f);
|
||||
addTest(29, 29, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public final class QRCodeBlackBox3TestCase extends AbstractBlackBoxTestCase {
|
|||
addTest(38, 38, 0.0f);
|
||||
addTest(38, 38, 90.0f);
|
||||
addTest(36, 36, 180.0f);
|
||||
addTest(38, 38, 270.0f);
|
||||
addTest(39, 39, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public final class QRCodeBlackBox4TestCase extends AbstractBlackBoxTestCase {
|
|||
addTest(36, 36, 0.0f);
|
||||
addTest(35, 35, 90.0f);
|
||||
addTest(35, 35, 180.0f);
|
||||
addTest(34, 34, 270.0f);
|
||||
addTest(35, 35, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public final class QRCodeBlackBox5TestCase extends AbstractBlackBoxTestCase {
|
|||
|
||||
public QRCodeBlackBox5TestCase() {
|
||||
super("test/data/blackbox/qrcode-5", new MultiFormatReader(), BarcodeFormat.QR_CODE);
|
||||
addTest(18, 18, 0.0f);
|
||||
addTest(19, 19, 0.0f);
|
||||
addTest(19, 19, 90.0f);
|
||||
addTest(19, 19, 180.0f);
|
||||
addTest(18, 18, 270.0f);
|
||||
|
|
|
@ -28,10 +28,10 @@ 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);
|
||||
addTest(15, 15, 0.0f);
|
||||
addTest(14, 14, 90.0f);
|
||||
addTest(12, 13, 180.0f);
|
||||
addTest(14, 14, 270.0f);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,6 @@ namespace {
|
|||
|
||||
HybridBinarizer::HybridBinarizer(Ref<LuminanceSource> source) :
|
||||
GlobalHistogramBinarizer(source), matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) {
|
||||
|
||||
}
|
||||
|
||||
HybridBinarizer::~HybridBinarizer() {
|
||||
|
@ -125,13 +124,21 @@ void HybridBinarizer::threshold8x8Block(unsigned char* luminances, int xoffset,
|
|||
y++, offset += stride) {
|
||||
for (int x = 0; x < BLOCK_SIZE; x++) {
|
||||
int pixel = luminances[offset + x] & 0xff;
|
||||
if (pixel < threshold) {
|
||||
if (pixel <= threshold) {
|
||||
matrix->set(xoffset + x, yoffset + y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
inline int getBlackPointFromNeighbors(int* blackPoints, int subWidth, int x, int y) {
|
||||
return (blackPoints[(y-1)*subWidth+x] +
|
||||
2*blackPoints[y*subWidth+x-1] +
|
||||
blackPoints[(y-1)*subWidth+x-1]) >> 2;
|
||||
}
|
||||
}
|
||||
|
||||
int* HybridBinarizer::calculateBlackPoints(unsigned char* luminances, int subWidth, int subHeight,
|
||||
int width, int height) {
|
||||
int *blackPoints = new int[subHeight * subWidth];
|
||||
|
@ -162,15 +169,18 @@ int* HybridBinarizer::calculateBlackPoints(unsigned char* luminances, int subWid
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the contrast is inadequate, use half the minimum, so that this block will be
|
||||
// treated as part of the white background, but won't drag down neighboring blocks
|
||||
// too much.
|
||||
int average;
|
||||
if (max - min > 24) {
|
||||
average = (sum >> 6);
|
||||
} else {
|
||||
average = max == 0 ? 1 : (min >> 1);
|
||||
|
||||
// See
|
||||
// http://groups.google.com/group/zxing/browse_thread/thread/d06efa2c35a7ddc0
|
||||
int average = sum >> 6;
|
||||
if (max - min <= 24) {
|
||||
average = min >> 1;
|
||||
if (y > 0 && x > 0) {
|
||||
int bp = getBlackPointFromNeighbors(blackPoints, subWidth, x, y);
|
||||
if (min < bp) {
|
||||
average = bp;
|
||||
}
|
||||
}
|
||||
}
|
||||
blackPoints[y * subWidth + x] = average;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue