refactoring in qzxing.cpp to remove uneeded references

This commit is contained in:
favoritas37 2016-03-18 21:01:48 +02:00
parent 3798e89fb6
commit 00d0e8d8d0
9 changed files with 193 additions and 221 deletions

View File

@ -157,45 +157,6 @@ ArrayRef<char> CameraImageWrapper::getMatrixP() const
return arr; return arr;
} }
QImage *CameraImageWrapper::sharpen(const QImage *origin)
{
QImage * newImage = new QImage(* origin);
int kernel [3][3]= {{0,-1,0},
{-1,5,-1},
{0,-1,0}};
int kernelSize = 3;
int sumKernel = 1;
int r,g,b;
QColor color;
for(int x=kernelSize/2; x<newImage->width()-(kernelSize/2); x++){
for(int y=kernelSize/2; y<newImage->height()-(kernelSize/2); y++){
r = 0;
g = 0;
b = 0;
for(int i = -kernelSize/2; i<= kernelSize/2; i++){
for(int j = -kernelSize/2; j<= kernelSize/2; j++){
color = QColor(origin->pixel(x+i, y+j));
r += color.red()*kernel[kernelSize/2+i][kernelSize/2+j];
g += color.green()*kernel[kernelSize/2+i][kernelSize/2+j];
b += color.blue()*kernel[kernelSize/2+i][kernelSize/2+j];
}
}
r = qBound(0, r/sumKernel, 255);
g = qBound(0, g/sumKernel, 255);
b = qBound(0, b/sumKernel, 255);
newImage->setPixel(x,y, qRgb(r,g,b));
}
}
return newImage;
}
unsigned int CameraImageWrapper::gray(unsigned int r, unsigned int g, unsigned int b) unsigned int CameraImageWrapper::gray(unsigned int r, unsigned int g, unsigned int b)
{ {
//values based on http://entropymine.com/imageworsener/grayscale/ //values based on http://entropymine.com/imageworsener/grayscale/

View File

@ -34,8 +34,6 @@ private:
ArrayRef<char> getMatrixP() const; ArrayRef<char> getMatrixP() const;
QImage* grayScaleImage(const QImage *origin); QImage* grayScaleImage(const QImage *origin);
QImage* sharpen(const QImage *origin);
unsigned int gray(unsigned int r, unsigned int g, unsigned int b); unsigned int gray(unsigned int r, unsigned int g, unsigned int b);
QImage* image; QImage* image;

View File

@ -198,25 +198,21 @@ QString QZXing::decodeImage(const QImage &image, int maxWidth, int maxHeight, bo
try { try {
Ref<LuminanceSource> imageRef(ciw); Ref<LuminanceSource> imageRef(ciw);
GlobalHistogramBinarizer *binz = new GlobalHistogramBinarizer(imageRef); Ref<GlobalHistogramBinarizer> binz( new GlobalHistogramBinarizer(imageRef) );
Ref<BinaryBitmap> bb( new BinaryBitmap(binz) );
Ref<Binarizer> bz(binz);
BinaryBitmap *bb = new BinaryBitmap(bz);
Ref<BinaryBitmap> ref(bb);
DecodeHints hints((int)enabledDecoders); DecodeHints hints((int)enabledDecoders);
bool hasSucceded = false; bool hasSucceded = false;
try { try {
res = decoder->decode(ref, hints); res = decoder->decode(bb, hints);
hasSucceded = true; hasSucceded = true;
}catch(zxing::Exception &e){} }catch(zxing::Exception &e){}
if(!hasSucceded) if(!hasSucceded)
{ {
hints.setTryHarder(true); hints.setTryHarder(true);
res = decoder->decode(ref, hints); res = decoder->decode(bb, hints);
} }
QString string = QString(res->getText()->getText().c_str()); QString string = QString(res->getText()->getText().c_str());

View File

@ -22,49 +22,53 @@ using zxing::BitArray;
using zxing::BitMatrix; using zxing::BitMatrix;
using zxing::LuminanceSource; using zxing::LuminanceSource;
using zxing::BinaryBitmap; using zxing::BinaryBitmap;
// VC++ // VC++
using zxing::Binarizer; using zxing::Binarizer;
BinaryBitmap::BinaryBitmap(Ref<Binarizer> binarizer) : binarizer_(binarizer) { BinaryBitmap::BinaryBitmap(Ref<Binarizer> binarizer) : binarizer_(binarizer) {
} }
BinaryBitmap::~BinaryBitmap() { BinaryBitmap::~BinaryBitmap() {
} }
Ref<BitArray> BinaryBitmap::getBlackRow(int y, Ref<BitArray> row) { Ref<BitArray> BinaryBitmap::getBlackRow(int y, Ref<BitArray> row) {
return binarizer_->getBlackRow(y, row); return binarizer_->getBlackRow(y, row);
} }
Ref<BitMatrix> BinaryBitmap::getBlackMatrix() { Ref<BitMatrix> BinaryBitmap::getBlackMatrix() {
return binarizer_->getBlackMatrix(); return binarizer_->getBlackMatrix();
} }
int BinaryBitmap::getWidth() const { int BinaryBitmap::getWidth() const {
return getLuminanceSource()->getWidth(); return getLuminanceSource()->getWidth();
} }
int BinaryBitmap::getHeight() const { int BinaryBitmap::getHeight() const {
return getLuminanceSource()->getHeight(); return getLuminanceSource()->getHeight();
} }
Ref<LuminanceSource> BinaryBitmap::getLuminanceSource() const { Ref<LuminanceSource> BinaryBitmap::getLuminanceSource() const {
return binarizer_->getLuminanceSource(); return binarizer_->getLuminanceSource();
} }
bool BinaryBitmap::isCropSupported() const { bool BinaryBitmap::isCropSupported() const {
return getLuminanceSource()->isCropSupported(); return getLuminanceSource()->isCropSupported();
} }
Ref<BinaryBitmap> BinaryBitmap::crop(int left, int top, int width, int height) { Ref<BinaryBitmap> BinaryBitmap::crop(int left, int top, int width, int height) {
return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->crop(left, top, width, height)))); return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->crop(left, top, width, height))));
} }
bool BinaryBitmap::isRotateSupported() const { bool BinaryBitmap::isRotateSupported() const {
return getLuminanceSource()->isRotateSupported(); return getLuminanceSource()->isRotateSupported();
} }
Ref<BinaryBitmap> BinaryBitmap::rotateCounterClockwise() { Ref<BinaryBitmap> BinaryBitmap::rotateCounterClockwise() {
return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->rotateCounterClockwise()))); return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->rotateCounterClockwise())));
}
Ref<zxing::BinaryBitmap> BinaryBitmap::rotateCounterClockwise45()
{
return Ref<BinaryBitmap> (new BinaryBitmap(binarizer_->createBinarizer(getLuminanceSource()->rotateCounterClockwise45())));
} }

View File

@ -45,10 +45,10 @@ namespace zxing {
bool isRotateSupported() const; bool isRotateSupported() const;
Ref<BinaryBitmap> rotateCounterClockwise(); Ref<BinaryBitmap> rotateCounterClockwise();
Ref<BinaryBitmap> rotateCounterClockwise45();
bool isCropSupported() const; bool isCropSupported() const;
Ref<BinaryBitmap> crop(int left, int top, int width, int height); Ref<BinaryBitmap> crop(int left, int top, int width, int height);
}; };
} }

View File

@ -43,7 +43,12 @@ bool LuminanceSource::isRotateSupported() const {
} }
Ref<LuminanceSource> LuminanceSource::rotateCounterClockwise() const { Ref<LuminanceSource> LuminanceSource::rotateCounterClockwise() const {
throw IllegalArgumentException("This luminance source does not support rotation."); throw IllegalArgumentException("This luminance source does not support rotation.");
}
Ref<zxing::LuminanceSource> LuminanceSource::rotateCounterClockwise45() const
{
throw IllegalArgumentException("This luminance source does not support rotation 45.");
} }
LuminanceSource::operator std::string() const { LuminanceSource::operator std::string() const {

View File

@ -51,6 +51,8 @@ class LuminanceSource : public Counted {
virtual Ref<LuminanceSource> rotateCounterClockwise() const; virtual Ref<LuminanceSource> rotateCounterClockwise() const;
virtual Ref<LuminanceSource> rotateCounterClockwise45() const;
operator std::string () const; operator std::string () const;
}; };

View File

@ -33,180 +33,181 @@ using zxing::BitMatrix;
using zxing::LuminanceSource; using zxing::LuminanceSource;
namespace { namespace {
const int LUMINANCE_BITS = 5; const int LUMINANCE_BITS = 5;
const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS; const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS; const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
const ArrayRef<char> EMPTY (0); const ArrayRef<char> EMPTY (0);
} }
GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source) GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref<LuminanceSource> source)
: Binarizer(source), luminances(EMPTY), buckets(LUMINANCE_BUCKETS) {} : Binarizer(source), luminances(EMPTY), buckets(LUMINANCE_BUCKETS) {}
GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {} GlobalHistogramBinarizer::~GlobalHistogramBinarizer() {}
void GlobalHistogramBinarizer::initArrays(int luminanceSize) { void GlobalHistogramBinarizer::initArrays(int luminanceSize) {
if (luminances->size() < luminanceSize) { if (luminances->size() < luminanceSize) {
luminances = ArrayRef<char>(luminanceSize); luminances = ArrayRef<char>(luminanceSize);
} }
for (int x = 0; x < LUMINANCE_BUCKETS; x++) { // for (int x = 0; x < LUMINANCE_BUCKETS; x++) {
buckets[x] = 0; // buckets[x] = 0;
} // }
memset(&buckets[0], 0, sizeof(int) * LUMINANCE_BUCKETS);
} }
Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) { Ref<BitArray> GlobalHistogramBinarizer::getBlackRow(int y, Ref<BitArray> row) {
// std::cerr << "gbr " << y << std::endl; // std::cerr << "gbr " << y << std::endl;
LuminanceSource& source = *getLuminanceSource(); LuminanceSource& source = *getLuminanceSource();
int width = source.getWidth(); int width = source.getWidth();
if (row == NULL || static_cast<int>(row->getSize()) < width) { if (row == NULL || static_cast<int>(row->getSize()) < width) {
row = new BitArray(width); row = new BitArray(width);
} else { } else {
row->clear(); row->clear();
}
initArrays(width);
ArrayRef<char> localLuminances = source.getRow(y, luminances);
if (false) {
std::cerr << "gbr " << y << " r ";
for(int i=0, e=localLuminances->size(); i < e; ++i) {
std::cerr << 0+localLuminances[i] << " ";
} }
std::cerr << std::endl;
}
ArrayRef<int> localBuckets = buckets;
for (int x = 0; x < width; x++) {
int pixel = localLuminances[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
}
int blackPoint = estimateBlackPoint(localBuckets);
// std::cerr << "gbr bp " << y << " " << blackPoint << std::endl;
int left = localLuminances[0] & 0xff; initArrays(width);
int center = localLuminances[1] & 0xff; ArrayRef<char> localLuminances = source.getRow(y, luminances);
for (int x = 1; x < width - 1; x++) { if (false) {
int right = localLuminances[x + 1] & 0xff; std::cerr << "gbr " << y << " r ";
// A simple -1 4 -1 box filter with a weight of 2. for(int i=0, e=localLuminances->size(); i < e; ++i) {
int luminance = ((center << 2) - left - right) >> 1; std::cerr << 0+localLuminances[i] << " ";
if (luminance < blackPoint) { }
row->set(x); std::cerr << std::endl;
} }
left = center; ArrayRef<int> localBuckets = buckets;
center = right;
}
return row;
}
Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() {
LuminanceSource& source = *getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
Ref<BitMatrix> matrix(new BitMatrix(width, height));
// Quickly calculates the histogram by sampling four rows from the image.
// This proved to be more robust on the blackbox tests than sampling a
// diagonal as we used to do.
initArrays(width);
ArrayRef<int> localBuckets = buckets;
for (int y = 1; y < 5; y++) {
int row = height * y / 5;
ArrayRef<char> localLuminances = source.getRow(row, luminances);
int right = (width << 2) / 5;
for (int x = width / 5; x < right; x++) {
int pixel = localLuminances[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
}
}
int blackPoint = estimateBlackPoint(localBuckets);
ArrayRef<char> localLuminances = source.getMatrix();
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
int pixel = localLuminances[offset + x] & 0xff; int pixel = localLuminances[x] & 0xff;
if (pixel < blackPoint) { localBuckets[pixel >> LUMINANCE_SHIFT]++;
matrix->set(x, y);
}
} }
} int blackPoint = estimateBlackPoint(localBuckets);
// std::cerr << "gbr bp " << y << " " << blackPoint << std::endl;
return matrix;
int left = localLuminances[0] & 0xff;
int center = localLuminances[1] & 0xff;
for (int x = 1; x < width - 1; x++) {
int right = localLuminances[x + 1] & 0xff;
// A simple -1 4 -1 box filter with a weight of 2.
int luminance = ((center << 2) - left - right) >> 1;
if (luminance < blackPoint) {
row->set(x);
}
left = center;
center = right;
}
return row;
}
Ref<BitMatrix> GlobalHistogramBinarizer::getBlackMatrix() {
LuminanceSource& source = *getLuminanceSource();
int width = source.getWidth();
int height = source.getHeight();
Ref<BitMatrix> matrix(new BitMatrix(width, height));
// Quickly calculates the histogram by sampling four rows from the image.
// This proved to be more robust on the blackbox tests than sampling a
// diagonal as we used to do.
initArrays(width);
ArrayRef<int> localBuckets = buckets;
for (int y = 1; y < 5; y++) {
int row = height * y / 5;
ArrayRef<char> localLuminances = source.getRow(row, luminances);
int right = (width << 2) / 5;
for (int x = width / 5; x < right; x++) {
int pixel = localLuminances[x] & 0xff;
localBuckets[pixel >> LUMINANCE_SHIFT]++;
}
}
int blackPoint = estimateBlackPoint(localBuckets);
ArrayRef<char> localLuminances = source.getMatrix();
for (int y = 0; y < height; y++) {
int offset = y * width;
for (int x = 0; x < width; x++) {
int pixel = localLuminances[offset + x] & 0xff;
if (pixel < blackPoint) {
matrix->set(x, y);
}
}
}
return matrix;
} }
using namespace std; using namespace std;
int GlobalHistogramBinarizer::estimateBlackPoint(ArrayRef<int> const& buckets) { int GlobalHistogramBinarizer::estimateBlackPoint(ArrayRef<int> const& buckets) {
// Find tallest peak in histogram // Find tallest peak in histogram
int numBuckets = buckets->size(); int numBuckets = buckets->size();
int maxBucketCount = 0; int maxBucketCount = 0;
int firstPeak = 0; int firstPeak = 0;
int firstPeakSize = 0; int firstPeakSize = 0;
if (false) { if (false) {
for (int x = 0; x < numBuckets; x++) {
cerr << buckets[x] << " ";
}
cerr << endl;
}
for (int x = 0; x < numBuckets; x++) { for (int x = 0; x < numBuckets; x++) {
cerr << buckets[x] << " "; if (buckets[x] > firstPeakSize) {
firstPeak = x;
firstPeakSize = buckets[x];
}
if (buckets[x] > maxBucketCount) {
maxBucketCount = buckets[x];
}
} }
cerr << endl;
} // Find second-tallest peak -- well, another peak that is tall and not
for (int x = 0; x < numBuckets; x++) { // so close to the first one
if (buckets[x] > firstPeakSize) { int secondPeak = 0;
firstPeak = x; int secondPeakScore = 0;
firstPeakSize = buckets[x]; for (int x = 0; x < numBuckets; x++) {
int distanceToBiggest = x - firstPeak;
// Encourage more distant second peaks by multiplying by square of distance
int score = buckets[x] * distanceToBiggest * distanceToBiggest;
if (score > secondPeakScore) {
secondPeak = x;
secondPeakScore = score;
}
} }
if (buckets[x] > maxBucketCount) {
maxBucketCount = buckets[x]; if (firstPeak > secondPeak) {
int temp = firstPeak;
firstPeak = secondPeak;
secondPeak = temp;
} }
}
// Find second-tallest peak -- well, another peak that is tall and not // Kind of arbitrary; if the two peaks are very close, then we figure there is
// so close to the first one // so little dynamic range in the image, that discriminating black and white
int secondPeak = 0; // is too error-prone.
int secondPeakScore = 0; // Decoding the image/line is either pointless, or may in some cases lead to
for (int x = 0; x < numBuckets; x++) { // a false positive for 1D formats, which are relatively lenient.
int distanceToBiggest = x - firstPeak; // We arbitrarily say "close" is
// Encourage more distant second peaks by multiplying by square of distance // "<= 1/16 of the total histogram buckets apart"
int score = buckets[x] * distanceToBiggest * distanceToBiggest; // std::cerr << "! " << secondPeak << " " << firstPeak << " " << numBuckets << std::endl;
if (score > secondPeakScore) { if (secondPeak - firstPeak <= numBuckets >> 4) {
secondPeak = x; throw NotFoundException();
secondPeakScore = score;
} }
}
if (firstPeak > secondPeak) { // Find a valley between them that is low and closer to the white peak
int temp = firstPeak; int bestValley = secondPeak - 1;
firstPeak = secondPeak; int bestValleyScore = -1;
secondPeak = temp; for (int x = secondPeak - 1; x > firstPeak; x--) {
} int fromFirst = x - firstPeak;
// Favor a "valley" that is not too close to either peak -- especially not
// Kind of arbitrary; if the two peaks are very close, then we figure there is // the black peak -- and that has a low value of course
// so little dynamic range in the image, that discriminating black and white int score = fromFirst * fromFirst * (secondPeak - x) *
// is too error-prone. (maxBucketCount - buckets[x]);
// Decoding the image/line is either pointless, or may in some cases lead to if (score > bestValleyScore) {
// a false positive for 1D formats, which are relatively lenient. bestValley = x;
// We arbitrarily say "close" is bestValleyScore = score;
// "<= 1/16 of the total histogram buckets apart" }
// std::cerr << "! " << secondPeak << " " << firstPeak << " " << numBuckets << std::endl;
if (secondPeak - firstPeak <= numBuckets >> 4) {
throw NotFoundException();
}
// Find a valley between them that is low and closer to the white peak
int bestValley = secondPeak - 1;
int bestValleyScore = -1;
for (int x = secondPeak - 1; x > firstPeak; x--) {
int fromFirst = x - firstPeak;
// Favor a "valley" that is not too close to either peak -- especially not
// the black peak -- and that has a low value of course
int score = fromFirst * fromFirst * (secondPeak - x) *
(maxBucketCount - buckets[x]);
if (score > bestValleyScore) {
bestValley = x;
bestValleyScore = score;
} }
}
// std::cerr << "bps " << (bestValley << LUMINANCE_SHIFT) << std::endl; // std::cerr << "bps " << (bestValley << LUMINANCE_SHIFT) << std::endl;
return bestValley << LUMINANCE_SHIFT; return bestValley << LUMINANCE_SHIFT;
} }
Ref<Binarizer> GlobalHistogramBinarizer::createBinarizer(Ref<LuminanceSource> source) { Ref<Binarizer> GlobalHistogramBinarizer::createBinarizer(Ref<LuminanceSource> source) {
return Ref<Binarizer> (new GlobalHistogramBinarizer(source)); return Ref<Binarizer> (new GlobalHistogramBinarizer(source));
} }

View File

@ -107,9 +107,7 @@ bool FinderPatternFinder::foundPatternCross(int* stateCount) {
float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal) { float FinderPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, int originalStateCountTotal) {
int maxI = image_->getHeight(); int maxI = image_->getHeight();
int stateCount[5] = {0}; int *stateCount = getCrossCheckStateCount();
// for (int i = 0; i < 5; i++)
// stateCount[i] = 0;
// Start counting up from center // Start counting up from center
@ -175,9 +173,7 @@ float FinderPatternFinder::crossCheckHorizontal(size_t startJ, size_t centerI, i
int originalStateCountTotal) { int originalStateCountTotal) {
int maxJ = image_->getWidth(); int maxJ = image_->getWidth();
int stateCount[5] = {0}; int *stateCount = getCrossCheckStateCount();
// for (int i = 0; i < 5; i++)
// stateCount[i] = 0;
int j = startJ; int j = startJ;
while (j >= 0 && image_->get(j, centerI)) { while (j >= 0 && image_->get(j, centerI)) {
@ -312,7 +308,7 @@ bool FinderPatternFinder::haveMultiplyConfirmedCenters() {
// and that we need to keep looking. We detect this by asking if the estimated module sizes // and that we need to keep looking. We detect this by asking if the estimated module sizes
// vary too much. We arbitrarily say that when the total deviation from average exceeds // vary too much. We arbitrarily say that when the total deviation from average exceeds
// 5% of the total module size estimates, it's too much. // 5% of the total module size estimates, it's too much.
float average = totalModuleSize / max; float average = totalModuleSize / (float)max;
float totalDeviation = 0.0f; float totalDeviation = 0.0f;
for (size_t i = 0; i < max; i++) { for (size_t i = 0; i < max; i++) {
Ref<FinderPattern> pattern = possibleCenters_[i]; Ref<FinderPattern> pattern = possibleCenters_[i];
@ -536,8 +532,17 @@ Ref<FinderPatternInfo> FinderPatternFinder::find(DecodeHints const& hints) {
} }
} }
vector<Ref<FinderPattern> > patternInfo = selectBestPatterns(); vector< Ref <FinderPattern> > patternInfo = selectBestPatterns();
patternInfo = orderBestPatterns(patternInfo); vector< Ref <ResultPoint> > patternInfoResPoints;
for(size_t i=0; i<patternInfo.size(); i++)
patternInfoResPoints.push_back(Ref<ResultPoint>(patternInfo[i]));
ResultPoint::orderBestPatterns(patternInfoResPoints);
patternInfo.clear();
for(size_t i=0; i<patternInfoResPoints.size(); i++)
patternInfo.push_back(Ref<FinderPattern>(static_cast<FinderPattern*>( &*patternInfoResPoints[i] )));
Ref<FinderPatternInfo> result(new FinderPatternInfo(patternInfo)); Ref<FinderPatternInfo> result(new FinderPatternInfo(patternInfo));
return result; return result;