Applied patch provided by Sergiy Korobov in Ticket #3 "Cannot detect QR code".

This commit is contained in:
favoritas37 2016-01-08 21:42:46 +02:00
parent b661cc2480
commit 6542fb1d6a
2 changed files with 101 additions and 18 deletions

View File

@ -47,6 +47,7 @@ protected:
bool hasSkipped_;
Ref<ResultPointCallback> callback_;
mutable int crossCheckStateCount[5];
/** stateCount must be int[5] */
static float centerFromEnd(int* stateCount, int end);
@ -65,6 +66,9 @@ protected:
Ref<BitMatrix> getImage();
std::vector<Ref<FinderPattern> >& getPossibleCenters();
bool crossCheckDiagonal(int startI, int centerJ, int maxCount, int originalStateCountTotal) const;
int *getCrossCheckStateCount() const;
public:
static float distance(Ref<ResultPoint> p1, Ref<ResultPoint> p2);
FinderPatternFinder(Ref<BitMatrix> image, Ref<ResultPointCallback>const&);

View File

@ -23,6 +23,7 @@
#include <zxing/qrcode/detector/FinderPatternFinder.h>
#include <zxing/ReaderException.h>
#include <zxing/DecodeHints.h>
#include <cstring>
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<FinderPatternInfo> 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<FinderPatternInfo> 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<BitMatrix> FinderPatternFinder::getImage() {
}
vector<Ref<FinderPattern> >& 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;
}