mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-12 21:21:42 +08:00
Making EAN/UPC/Code128 Readers more restrictive; Added alternative Method for binarizing Scanline
This commit is contained in:
+12
-4
@@ -340,16 +340,24 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
||||
* @returns {Array} list of patches
|
||||
*/
|
||||
function describePatch(moments, patchPos, x, y) {
|
||||
var k, avg, sum = 0, eligibleMoments = [], matchingMoments, patch, patchesFound = [];
|
||||
var k,
|
||||
avg,
|
||||
sum = 0,
|
||||
eligibleMoments = [],
|
||||
matchingMoments,
|
||||
patch,
|
||||
patchesFound = [],
|
||||
minComponentWeight = Math.ceil(_patchSize.x/3);
|
||||
|
||||
if (moments.length >= 2) {
|
||||
// only collect moments which's area covers at least 6 pixels.
|
||||
// only collect moments which's area covers at least minComponentWeight pixels.
|
||||
for ( k = 0; k < moments.length; k++) {
|
||||
if (moments[k].m00 > 6) {
|
||||
if (moments[k].m00 > minComponentWeight) {
|
||||
eligibleMoments.push(moments[k]);
|
||||
}
|
||||
}
|
||||
|
||||
// if at least 2 moments are found which have 6pixels covered
|
||||
// if at least 2 moments are found which have at least minComponentWeights covered
|
||||
if (eligibleMoments.length >= 2) {
|
||||
sum = eligibleMoments.length;
|
||||
matchingMoments = similarMoments(eligibleMoments);
|
||||
|
||||
+10
-3
@@ -26,12 +26,19 @@ define(
|
||||
|
||||
BarcodeReader.prototype._matchPattern = function(counter, code) {
|
||||
var i,
|
||||
error = 0;
|
||||
error = 0,
|
||||
singleError = 0,
|
||||
modulo = this.MODULO,
|
||||
maxSingleError = 0.9;
|
||||
|
||||
for (i = 0; i < counter.length; i++) {
|
||||
error += Math.abs(code[i] - counter[i]);
|
||||
singleError = Math.abs(code[i] - counter[i]);
|
||||
if (singleError > maxSingleError) {
|
||||
return Number.MAX_VALUE;
|
||||
}
|
||||
error += singleError;
|
||||
}
|
||||
return error;
|
||||
return error/modulo;
|
||||
};
|
||||
|
||||
BarcodeReader.prototype._nextSet = function(line, offset) {
|
||||
|
||||
+15
-1
@@ -1,7 +1,7 @@
|
||||
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||
/* global define */
|
||||
|
||||
define(function() {
|
||||
define(["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper) {
|
||||
"use strict";
|
||||
var Bresenham = {};
|
||||
|
||||
@@ -91,6 +91,20 @@ define(function() {
|
||||
max : max
|
||||
};
|
||||
};
|
||||
|
||||
Bresenham.toOtsuBinaryLine = function(result) {
|
||||
var line = result.line,
|
||||
image = new ImageWrapper({x: line.length - 1, y: 1}, line),
|
||||
threshold = CVUtils.determineOtsuThreshold(image, 5);
|
||||
|
||||
line = CVUtils.sharpenLine(line);
|
||||
CVUtils.thresholdImage(image, threshold);
|
||||
|
||||
return {
|
||||
line: line,
|
||||
threshold: threshold
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts the result from getBarcodeLine into a binary representation
|
||||
|
||||
+45
-14
@@ -119,22 +119,46 @@ define(['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrix
|
||||
}
|
||||
};
|
||||
|
||||
CVUtils.computeHistogram = function(imageWrapper) {
|
||||
var imageData = imageWrapper.data, length = imageData.length, i, hist = new Int32Array(256);
|
||||
|
||||
// init histogram
|
||||
for ( i = 0; i < 256; i++) {
|
||||
hist[i] = 0;
|
||||
CVUtils.computeHistogram = function(imageWrapper, bitsPerPixel) {
|
||||
if (!bitsPerPixel) {
|
||||
bitsPerPixel = 8;
|
||||
}
|
||||
var imageData = imageWrapper.data,
|
||||
length = imageData.length,
|
||||
bitShift = 8 - bitsPerPixel,
|
||||
bucketCnt = 1 << bitsPerPixel,
|
||||
hist = new Int32Array(bucketCnt);
|
||||
|
||||
while (length--) {
|
||||
hist[imageData[length]]++;
|
||||
hist[imageData[length] >> bitShift]++;
|
||||
}
|
||||
return hist;
|
||||
};
|
||||
|
||||
CVUtils.otsuThreshold = function(imageWrapper, targetWrapper) {
|
||||
var hist, threshold;
|
||||
CVUtils.sharpenLine = function(line) {
|
||||
var i,
|
||||
length = line.length,
|
||||
left = line[0],
|
||||
center = line[1],
|
||||
right;
|
||||
|
||||
for (i = 1; i < length - 1; i++) {
|
||||
right = line[i + 1];
|
||||
// -1 4 -1 kernel
|
||||
line[i-1] = (((center * 2) - left - right)) & 255;
|
||||
left = center;
|
||||
center = right;
|
||||
}
|
||||
return line;
|
||||
};
|
||||
|
||||
CVUtils.determineOtsuThreshold = function(imageWrapper, bitsPerPixel) {
|
||||
if (!bitsPerPixel) {
|
||||
bitsPerPixel = 8;
|
||||
}
|
||||
var hist,
|
||||
threshold,
|
||||
bitShift = 8 - bitsPerPixel;
|
||||
|
||||
function px(init, end) {
|
||||
var sum = 0, i;
|
||||
@@ -155,18 +179,19 @@ define(['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrix
|
||||
}
|
||||
|
||||
function determineThreshold() {
|
||||
var vet = [0], p1, p2, p12, k, m1, m2, m12;
|
||||
var vet = [0], p1, p2, p12, k, m1, m2, m12,
|
||||
max = (1 << bitsPerPixel) - 1;
|
||||
|
||||
hist = CVUtils.computeHistogram(imageWrapper);
|
||||
for ( k = 1; k < 255; k++) {
|
||||
hist = CVUtils.computeHistogram(imageWrapper, bitsPerPixel);
|
||||
for ( k = 1; k < max; k++) {
|
||||
p1 = px(0, k);
|
||||
p2 = px(k + 1, 255);
|
||||
p2 = px(k + 1, max);
|
||||
p12 = p1 * p2;
|
||||
if (p12 === 0) {
|
||||
p12 = 1;
|
||||
}
|
||||
m1 = mx(0, k) * p2;
|
||||
m2 = mx(k + 1, 255) * p1;
|
||||
m2 = mx(k + 1, max) * p1;
|
||||
m12 = m1 - m2;
|
||||
vet[k] = m12 * m12 / p12;
|
||||
}
|
||||
@@ -174,6 +199,12 @@ define(['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrix
|
||||
}
|
||||
|
||||
threshold = determineThreshold();
|
||||
return threshold << bitShift;
|
||||
};
|
||||
|
||||
CVUtils.otsuThreshold = function(imageWrapper, targetWrapper) {
|
||||
var threshold = CVUtils.determineOtsuThreshold(imageWrapper);
|
||||
|
||||
CVUtils.thresholdImage(imageWrapper, threshold, targetWrapper);
|
||||
return threshold;
|
||||
};
|
||||
|
||||
+25
-7
@@ -82,6 +82,9 @@ define(
|
||||
}
|
||||
}
|
||||
bestMatch.end = i;
|
||||
if (bestMatch.error > 0.5) {
|
||||
return null;
|
||||
}
|
||||
return bestMatch;
|
||||
} else {
|
||||
counterPos++;
|
||||
@@ -122,7 +125,7 @@ define(
|
||||
}
|
||||
|
||||
if ( epsilon === undefined) {
|
||||
epsilon = 1.5;
|
||||
epsilon = 0.5;
|
||||
}
|
||||
|
||||
for ( i = 0; i < pattern.length; i++) {
|
||||
@@ -206,13 +209,29 @@ define(
|
||||
return self._verifyTrailingWhitespace(endInfo);
|
||||
};
|
||||
|
||||
EANReader.prototype._calculateFirstDigit = function(codeFrequency) {
|
||||
var i,
|
||||
self = this;
|
||||
|
||||
for ( i = 0; i < self.CODE_FREQUENCY.length; i++) {
|
||||
if (codeFrequency === self.CODE_FREQUENCY[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
EANReader.prototype._decodePayload = function(code, result, decodedCodes) {
|
||||
var i,
|
||||
self = this,
|
||||
codeFrequency = 0x0;
|
||||
codeFrequency = 0x0,
|
||||
firstDigit;
|
||||
|
||||
for ( i = 0; i < 6; i++) {
|
||||
code = self._decodeCode(code.end);
|
||||
if (!code) {
|
||||
return null;
|
||||
}
|
||||
if (code.code >= self.CODE_G_START) {
|
||||
code.code = code.code - self.CODE_G_START;
|
||||
codeFrequency |= 1 << (5 - i);
|
||||
@@ -223,12 +242,11 @@ define(
|
||||
decodedCodes.push(code);
|
||||
}
|
||||
|
||||
for ( i = 0; i < self.CODE_FREQUENCY.length; i++) {
|
||||
if (codeFrequency === self.CODE_FREQUENCY[i]) {
|
||||
result.unshift(i);
|
||||
break;
|
||||
}
|
||||
firstDigit = self._calculateFirstDigit(codeFrequency);
|
||||
if (firstDigit === null) {
|
||||
return null;
|
||||
}
|
||||
result.unshift(firstDigit);
|
||||
|
||||
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false);
|
||||
if (code === null) {
|
||||
|
||||
Reference in New Issue
Block a user