From 6542fb1d6a3b9d6b73d5e6643981977df880921b Mon Sep 17 00:00:00 2001 From: favoritas37 Date: Fri, 8 Jan 2016 21:42:46 +0200 Subject: [PATCH] Applied patch provided by Sergiy Korobov in Ticket #3 "Cannot detect QR code". --- .../qrcode/detector/FinderPatternFinder.h | 4 + .../qrcode/detector/QRFinderPatternFinder.cpp | 115 +++++++++++++++--- 2 files changed, 101 insertions(+), 18 deletions(-) diff --git a/source/zxing/zxing/qrcode/detector/FinderPatternFinder.h b/source/zxing/zxing/qrcode/detector/FinderPatternFinder.h index 82d4365..af4a438 100644 --- a/source/zxing/zxing/qrcode/detector/FinderPatternFinder.h +++ b/source/zxing/zxing/qrcode/detector/FinderPatternFinder.h @@ -47,6 +47,7 @@ protected: bool hasSkipped_; Ref callback_; + mutable int crossCheckStateCount[5]; /** stateCount must be int[5] */ static float centerFromEnd(int* stateCount, int end); @@ -65,6 +66,9 @@ protected: Ref getImage(); std::vector >& getPossibleCenters(); + bool crossCheckDiagonal(int startI, int centerJ, int maxCount, int originalStateCountTotal) const; + int *getCrossCheckStateCount() const; + public: static float distance(Ref p1, Ref p2); FinderPatternFinder(Ref image, Refconst&); diff --git a/source/zxing/zxing/qrcode/detector/QRFinderPatternFinder.cpp b/source/zxing/zxing/qrcode/detector/QRFinderPatternFinder.cpp index 3a4f71d..ada5248 100644 --- a/source/zxing/zxing/qrcode/detector/QRFinderPatternFinder.cpp +++ b/source/zxing/zxing/qrcode/detector/QRFinderPatternFinder.cpp @@ -23,6 +23,7 @@ #include #include #include +#include using std::sort; using std::max; @@ -106,9 +107,9 @@ bool FinderPatternFinder::foundPatternCross(int* stateCount) { float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal) { int maxI = image_->getHeight(); - int stateCount[5]; - for (int i = 0; i < 5; i++) - stateCount[i] = 0; + int stateCount[5] = {0}; +// for (int i = 0; i < 5; i++) +// stateCount[i] = 0; // Start counting up from center @@ -174,9 +175,9 @@ float FinderPatternFinder::crossCheckHorizontal(size_t startJ, size_t centerI, i int originalStateCountTotal) { int maxJ = image_->getWidth(); - int stateCount[5]; - for (int i = 0; i < 5; i++) - stateCount[i] = 0; + int stateCount[5] = {0}; +// for (int i = 0; i < 5; i++) +// stateCount[i] = 0; int j = startJ; while (j >= 0 && image_->get(j, centerI)) { @@ -241,7 +242,7 @@ bool FinderPatternFinder::handlePossibleCenter(int* stateCount, size_t i, size_t if (!isnan_z(centerI)) { // Re-cross check centerJ = crossCheckHorizontal((size_t)centerJ, (size_t)centerI, stateCount[2], stateCountTotal); - if (!isnan_z(centerJ)) { + if (!isnan_z(centerJ) && crossCheckDiagonal((int)centerI, (int)centerJ, stateCount[2], stateCountTotal)) { float estimatedModuleSize = (float)stateCountTotal / 7.0f; bool found = false; size_t max = possibleCenters_.size(); @@ -459,11 +460,7 @@ Ref FinderPatternFinder::find(DecodeHints const& hints) { for (size_t i = iSkip - 1; i < maxI && !done; i += iSkip) { // Get a row of black/white values - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; + memset(stateCount, 0, sizeof(stateCount)); int currentState = 0; for (size_t j = 0; j < maxJ; j++) { if (matrix.get(j, i)) { @@ -510,11 +507,7 @@ Ref FinderPatternFinder::find(DecodeHints const& hints) { } // Clear state to start looking again currentState = 0; - stateCount[0] = 0; - stateCount[1] = 0; - stateCount[2] = 0; - stateCount[3] = 0; - stateCount[4] = 0; + memset(stateCount, 0, sizeof(stateCount)); } else { // No, shift counts back by two stateCount[0] = stateCount[2]; stateCount[1] = stateCount[3]; @@ -555,5 +548,91 @@ Ref FinderPatternFinder::getImage() { } vector >& FinderPatternFinder::getPossibleCenters() { - return possibleCenters_; + return possibleCenters_; +} + +bool FinderPatternFinder::crossCheckDiagonal(int startI, int centerJ, int maxCount, int originalStateCountTotal) const +{ + int *stateCount = getCrossCheckStateCount(); + + // Start counting up, left from center finding black center mass + int i = 0; + while (startI >= i && centerJ >= i && image_->get(centerJ - i, startI - i)) { + stateCount[2]++; + i++; + } + + if (startI < i || centerJ < i) { + return false; + } + + // Continue up, left finding white space + while (startI >= i && centerJ >= i && !image_->get(centerJ - i, startI - i) && + stateCount[1] <= maxCount) { + stateCount[1]++; + i++; + } + + // If already too many modules in this state or ran off the edge: + if (startI < i || centerJ < i || stateCount[1] > maxCount) { + return false; + } + + // Continue up, left finding black border + while (startI >= i && centerJ >= i && image_->get(centerJ - i, startI - i) && + stateCount[0] <= maxCount) { + stateCount[0]++; + i++; + } + if (stateCount[0] > maxCount) { + return false; + } + + int maxI = image_->getHeight(); + int maxJ = image_->getWidth(); + + // Now also count down, right from center + i = 1; + while (startI + i < maxI && centerJ + i < maxJ && image_->get(centerJ + i, startI + i)) { + stateCount[2]++; + i++; + } + + // Ran off the edge? + if (startI + i >= maxI || centerJ + i >= maxJ) { + return false; + } + + while (startI + i < maxI && centerJ + i < maxJ && !image_->get(centerJ + i, startI + i) && + stateCount[3] < maxCount) { + stateCount[3]++; + i++; + } + + if (startI + i >= maxI || centerJ + i >= maxJ || stateCount[3] >= maxCount) { + return false; + } + + while (startI + i < maxI && centerJ + i < maxJ && image_->get(centerJ + i, startI + i) && + stateCount[4] < maxCount) { + stateCount[4]++; + i++; + } + + if (stateCount[4] >= maxCount) { + return false; + } + + // If we found a finder-pattern-like section, but its size is more than 100% different than + // the original, assume it's a false positive + int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] + stateCount[4]; + return + abs(stateCountTotal - originalStateCountTotal) < 2 * originalStateCountTotal && + foundPatternCross(stateCount); +} + +int *FinderPatternFinder::getCrossCheckStateCount() const +{ + memset(crossCheckStateCount, 0, sizeof(crossCheckStateCount)); + return crossCheckStateCount; }