updated to 0.6.3

gh-pages
Christoph Oberhofer 10 years ago
parent 6e803c937b
commit 2a7ab5d12d

@ -460,12 +460,19 @@ define(
BarcodeReader.prototype._matchPattern = function(counter, code) { BarcodeReader.prototype._matchPattern = function(counter, code) {
var i, var i,
error = 0; error = 0,
singleError = 0,
modulo = this.MODULO,
maxSingleError = this.SINGLE_CODE_ERROR || 1;
for (i = 0; i < counter.length; i++) { 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;
} }
return error; error += singleError;
}
return error/modulo;
}; };
BarcodeReader.prototype._nextSet = function(line, offset) { BarcodeReader.prototype._nextSet = function(line, offset) {
@ -755,7 +762,9 @@ define(
[2, 1, 1, 2, 1, 4], [2, 1, 1, 2, 1, 4],
[2, 1, 1, 2, 3, 2], [2, 1, 1, 2, 3, 2],
[2, 3, 3, 1, 1, 1, 2] [2, 3, 3, 1, 1, 1, 2]
]} ]},
SINGLE_CODE_ERROR: {value: 1},
AVG_CODE_ERROR: {value: 0.5}
}; };
Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties); Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties);
@ -832,7 +841,7 @@ define(
} }
normalized = self._normalize(counter, 13); normalized = self._normalize(counter, 13);
error = self._matchPattern(normalized, self.CODE_PATTERN[self.STOP_CODE]); error = self._matchPattern(normalized, self.CODE_PATTERN[self.STOP_CODE]);
if (error < 3) { if (error < self.AVG_CODE_ERROR) {
bestMatch.error = error; bestMatch.error = error;
bestMatch.start = i - sum; bestMatch.start = i - sum;
bestMatch.end = i; bestMatch.end = i;
@ -891,7 +900,7 @@ define(
bestMatch.error = error; bestMatch.error = error;
} }
} }
if (bestMatch.error < 3) { if (bestMatch.error < self.AVG_CODE_ERROR) {
bestMatch.start = i - sum; bestMatch.start = i - sum;
bestMatch.end = i; bestMatch.end = i;
return bestMatch; return bestMatch;
@ -1114,7 +1123,9 @@ define(
[3, 1, 2, 1], [3, 1, 2, 1],
[2, 1, 1, 3] [2, 1, 1, 3]
]}, ]},
CODE_FREQUENCY : {value: [0, 11, 13, 14, 19, 25, 28, 21, 22, 26]} CODE_FREQUENCY : {value: [0, 11, 13, 14, 19, 25, 28, 21, 22, 26]},
SINGLE_CODE_ERROR: {value: 1},
AVG_CODE_ERROR: {value: 0.5}
}; };
EANReader.prototype = Object.create(BarcodeReader.prototype, properties); EANReader.prototype = Object.create(BarcodeReader.prototype, properties);
@ -1155,6 +1166,9 @@ define(
} }
} }
bestMatch.end = i; bestMatch.end = i;
if (bestMatch.error > self.AVG_CODE_ERROR) {
return null;
}
return bestMatch; return bestMatch;
} else { } else {
counterPos++; counterPos++;
@ -1195,7 +1209,7 @@ define(
} }
if ( epsilon === undefined) { if ( epsilon === undefined) {
epsilon = 1.5; epsilon = self.AVG_CODE_ERROR;
} }
for ( i = 0; i < pattern.length; i++) { for ( i = 0; i < pattern.length; i++) {
@ -1279,13 +1293,29 @@ define(
return self._verifyTrailingWhitespace(endInfo); 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) { EANReader.prototype._decodePayload = function(code, result, decodedCodes) {
var i, var i,
self = this, self = this,
codeFrequency = 0x0; codeFrequency = 0x0,
firstDigit;
for ( i = 0; i < 6; i++) { for ( i = 0; i < 6; i++) {
code = self._decodeCode(code.end); code = self._decodeCode(code.end);
if (!code) {
return null;
}
if (code.code >= self.CODE_G_START) { if (code.code >= self.CODE_G_START) {
code.code = code.code - self.CODE_G_START; code.code = code.code - self.CODE_G_START;
codeFrequency |= 1 << (5 - i); codeFrequency |= 1 << (5 - i);
@ -1296,12 +1326,11 @@ define(
decodedCodes.push(code); decodedCodes.push(code);
} }
for ( i = 0; i < self.CODE_FREQUENCY.length; i++) { firstDigit = self._calculateFirstDigit(codeFrequency);
if (codeFrequency === self.CODE_FREQUENCY[i]) { if (firstDigit === null) {
result.unshift(i); return null;
break;
}
} }
result.unshift(firstDigit);
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false); code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false);
if (code === null) { if (code === null) {
@ -4377,22 +4406,46 @@ define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster
} }
}; };
CVUtils.computeHistogram = function(imageWrapper) { CVUtils.computeHistogram = function(imageWrapper, bitsPerPixel) {
var imageData = imageWrapper.data, length = imageData.length, i, hist = new Int32Array(256); if (!bitsPerPixel) {
bitsPerPixel = 8;
// init histogram
for ( i = 0; i < 256; i++) {
hist[i] = 0;
} }
var imageData = imageWrapper.data,
length = imageData.length,
bitShift = 8 - bitsPerPixel,
bucketCnt = 1 << bitsPerPixel,
hist = new Int32Array(bucketCnt);
while (length--) { while (length--) {
hist[imageData[length]]++; hist[imageData[length] >> bitShift]++;
} }
return hist; return hist;
}; };
CVUtils.otsuThreshold = function(imageWrapper, targetWrapper) { CVUtils.sharpenLine = function(line) {
var hist, threshold; 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) { function px(init, end) {
var sum = 0, i; var sum = 0, i;
@ -4413,18 +4466,19 @@ define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster
} }
function determineThreshold() { 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); hist = CVUtils.computeHistogram(imageWrapper, bitsPerPixel);
for ( k = 1; k < 255; k++) { for ( k = 1; k < max; k++) {
p1 = px(0, k); p1 = px(0, k);
p2 = px(k + 1, 255); p2 = px(k + 1, max);
p12 = p1 * p2; p12 = p1 * p2;
if (p12 === 0) { if (p12 === 0) {
p12 = 1; p12 = 1;
} }
m1 = mx(0, k) * p2; m1 = mx(0, k) * p2;
m2 = mx(k + 1, 255) * p1; m2 = mx(k + 1, max) * p1;
m12 = m1 - m2; m12 = m1 - m2;
vet[k] = m12 * m12 / p12; vet[k] = m12 * m12 / p12;
} }
@ -4432,6 +4486,12 @@ define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster
} }
threshold = determineThreshold(); threshold = determineThreshold();
return threshold << bitShift;
};
CVUtils.otsuThreshold = function(imageWrapper, targetWrapper) {
var threshold = CVUtils.determineOtsuThreshold(imageWrapper);
CVUtils.thresholdImage(imageWrapper, threshold, targetWrapper); CVUtils.thresholdImage(imageWrapper, threshold, targetWrapper);
return threshold; return threshold;
}; };
@ -6203,16 +6263,24 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
* @returns {Array} list of patches * @returns {Array} list of patches
*/ */
function describePatch(moments, patchPos, x, y) { 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) { 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++) { for ( k = 0; k < moments.length; k++) {
if (moments[k].m00 > 6) { if (moments[k].m00 > minComponentWeight) {
eligibleMoments.push(moments[k]); 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) { if (eligibleMoments.length >= 2) {
sum = eligibleMoments.length; sum = eligibleMoments.length;
matchingMoments = similarMoments(eligibleMoments); matchingMoments = similarMoments(eligibleMoments);
@ -6379,7 +6447,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
/* jshint undef: true, unused: true, browser:true, devel: true */ /* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */ /* global define */
define('bresenham',[],function() { define('bresenham',["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper) {
var Bresenham = {}; var Bresenham = {};
@ -6470,6 +6538,20 @@ define('bresenham',[],function() {
}; };
}; };
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 * Converts the result from getBarcodeLine into a binary representation
* also considering the frequency and slope of the signal for more robust results * also considering the frequency and slope of the signal for more robust results
@ -6526,9 +6608,9 @@ define('bresenham',[],function() {
// iterate over extrema and convert to binary based on avg between minmax // iterate over extrema and convert to binary based on avg between minmax
for ( i = 1; i < extrema.length - 1; i++) { for ( i = 1; i < extrema.length - 1; i++) {
if (extrema[i + 1].val > extrema[i].val) { if (extrema[i + 1].val > extrema[i].val) {
threshold = (extrema[i].val + (extrema[i + 1].val - extrema[i].val) / 2) | 0; threshold = (extrema[i].val + ((extrema[i + 1].val - extrema[i].val) / 3) * 2) | 0;
} else { } else {
threshold = (extrema[i + 1].val + (extrema[i].val - extrema[i + 1].val) / 2) | 0; threshold = (extrema[i + 1].val + ((extrema[i].val - extrema[i + 1].val) / 3)) | 0;
} }
for ( j = extrema[i].pos; j < extrema[i + 1].pos; j++) { for ( j = extrema[i].pos; j < extrema[i + 1].pos; j++) {
@ -6783,6 +6865,66 @@ define(
/* jshint undef: true, unused: true, browser:true, devel: true */ /* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */ /* global define */
define(
'code_39_vin_reader',[
"./code_39_reader"
],
function(Code39Reader) {
function Code39VINReader() {
Code39Reader.call(this);
}
var patterns = {
IOQ: /[IOQ]/g,
AZ09: /[A-Z0-9]{17}/
};
Code39VINReader.prototype = Object.create(Code39Reader.prototype);
Code39VINReader.prototype.constructor = Code39VINReader;
// Cribbed from:
// https://github.com/zxing/zxing/blob/master/core/src/main/java/com/google/zxing/client/result/VINResultParser.java
Code39VINReader.prototype._decode = function() {
var result = Code39Reader.prototype._decode.apply(this);
if (!result) {
return null;
}
var code = result.code;
if (!code) {
return;
}
code = code.replace(patterns.IOQ, '');
if (!code.match(patterns.AZ09)) {
console.log('Failed AZ09 pattern code:', code);
return null;
}
if (!this._checkChecksum(code)) {
return null;
}
result.code = code;
return result;
};
Code39VINReader.prototype._checkChecksum = function(code) {
// TODO
return !!code;
};
return (Code39VINReader);
}
);
/* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */
define( define(
'codabar_reader',[ 'codabar_reader',[
"./barcode_reader" "./barcode_reader"
@ -7287,6 +7429,7 @@ define('barcode_decoder',[
'code_128_reader', 'code_128_reader',
'ean_reader', 'ean_reader',
'code_39_reader', 'code_39_reader',
'code_39_vin_reader',
'codabar_reader', 'codabar_reader',
'upc_reader', 'upc_reader',
'ean_8_reader', 'ean_8_reader',
@ -7297,6 +7440,7 @@ define('barcode_decoder',[
Code128Reader, Code128Reader,
EANReader, EANReader,
Code39Reader, Code39Reader,
Code39VINReader,
CodabarReader, CodabarReader,
UPCReader, UPCReader,
EAN8Reader, EAN8Reader,
@ -7308,6 +7452,7 @@ define('barcode_decoder',[
ean_reader: EANReader, ean_reader: EANReader,
ean_8_reader: EAN8Reader, ean_8_reader: EAN8Reader,
code_39_reader: Code39Reader, code_39_reader: Code39Reader,
code_39_vin_reader: Code39VINReader,
codabar_reader: CodabarReader, codabar_reader: CodabarReader,
upc_reader: UPCReader, upc_reader: UPCReader,
upc_e_reader: UPCEReader upc_e_reader: UPCEReader
@ -7574,6 +7719,7 @@ define('barcode_decoder',[
return (BarcodeDecoder); return (BarcodeDecoder);
}); });
/* jshint undef: true, unused: true, browser:true, devel: true */ /* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */ /* global define */
@ -7707,6 +7853,8 @@ define('config',[],function(){
constraints: { constraints: {
width: 640, width: 640,
height: 480, height: 480,
minAspectRatio: 0,
maxAspectRatio: 100,
facing: "environment" // or user facing: "environment" // or user
} }
}, },
@ -7747,6 +7895,7 @@ define('config',[],function(){
return config; return config;
}); });
/* jshint undef: true, unused: true, browser:true, devel: true */ /* jshint undef: true, unused: true, browser:true, devel: true */
/* global define */ /* global define */
@ -7914,6 +8063,8 @@ define('camera_access',["html_utils"], function(HtmlUtils) {
videoConstraints = HtmlUtils.mergeObjects({ videoConstraints = HtmlUtils.mergeObjects({
width: 640, width: 640,
height: 480, height: 480,
minAspectRatio: 0,
maxAspectRatio: 100,
facing: "environment" facing: "environment"
}, config); }, config);
@ -7929,7 +8080,9 @@ define('camera_access',["html_utils"], function(HtmlUtils) {
constraints.video = { constraints.video = {
mandatory: { mandatory: {
minWidth: videoConstraints.width, minWidth: videoConstraints.width,
minHeight: videoConstraints.height minHeight: videoConstraints.height,
minAspectRatio: videoConstraints.minAspectRatio,
maxAspectRatio: videoConstraints.maxAspectRatio
}, },
optional: [{ optional: [{
sourceId: videoSourceId sourceId: videoSourceId
@ -7973,6 +8126,7 @@ define('camera_access',["html_utils"], function(HtmlUtils) {
} }
}; };
}); });
/* jshint undef: true, unused: true, browser:true, devel: true, evil: true */ /* jshint undef: true, unused: true, browser:true, devel: true, evil: true */
/* global define, vec2 */ /* global define, vec2 */
@ -8427,7 +8581,7 @@ function(Code128Reader,
} }
}, config); }, config);
this.init(config, function() { this.init(config, function() {
Events.once("detected", function(result) { Events.once("processed", function(result) {
_stopped = true; _stopped = true;
resultCallback.call(null, result); resultCallback.call(null, result);
}, true); }, true);

File diff suppressed because one or more lines are too long

@ -7,7 +7,7 @@ showInMenu: true
quaggaJS quaggaJS
======== ========
- [Changelog](#changelog) (2015-05-09) - [Changelog](#changelog) (2015-05-18)
## What is QuaggaJS? ## What is QuaggaJS?
@ -299,6 +299,11 @@ work.
## <a name="changelog">Changelog</a> ## <a name="changelog">Changelog</a>
### 2015-05-18
- Improvements
- Making EAN and UPC readers more restrictive
- Added integration-tests for all barcode-readers
### 2015-05-09 ### 2015-05-09
- Improvements - Improvements
- Odd image dimensions no longer cause problems - Odd image dimensions no longer cause problems

Loading…
Cancel
Save