194: Added basic support for 2of5 barcodes; fixed integration-tests

pull/196/head
Christoph Oberhofer 8 years ago
parent f9a19e0a02
commit 06bcda3157

@ -52,6 +52,7 @@
<option value="upc_e">UPC-E</option>
<option value="codabar">Codabar</option>
<option value="i2of5">ITF</option>
<option value="2of5">2of5</option>
</select>
</label>
<label>

@ -43,7 +43,8 @@
<option value="upc">UPC</option>
<option value="upc_e">UPC-E</option>
<option value="codabar">Codabar</option>
<option value="i2of5">ITF</option>
<option value="i2of5">Interleaved 2 of 5</option>
<option value="2of5">Standard 2 of 5</option>
</select>
</label>
<label>

@ -2,7 +2,19 @@ $(function() {
var resultCollector = Quagga.ResultCollector.create({
capture: true,
capacity: 20,
blacklist: [{code: "2167361334", format: "i2of5"}],
blacklist: [{
code: "9577149002", format: "2of5"
}, {
code: "5776158811", format: "2of5"
}, {
code: "0463381455", format: "2of5"
}, {
code: "3261594101", format: "2of5"
}, {
code: "6730705801", format: "2of5"
}, {
code: "8568166929", format: "2of5"
}],
filter: function(codeResult) {
// only store results which match this constraint
// e.g.: codeResult
@ -169,7 +181,8 @@ $(function() {
patchSize: "medium",
halfSample: true
},
numOfWorkers: 4,
numOfWorkers: 2,
frequency: 10,
decoder: {
readers : [{
format: "code_128_reader",

@ -45,6 +45,8 @@
<option value="upc_e">UPC-E</option>
<option value="codabar">Codabar</option>
<option value="i2of5">I2of5</option>
<option value="i2of5">Interleaved 2 of 5</option>
<option value="2of5">Standard 2 of 5</option>
</select>
</fieldset>
</div>

@ -14,6 +14,9 @@ module.exports = function(config) {
'test/test-main-integration.js': ['webpack']
},
webpack: {
entry: [
'./src/quagga.js'
],
module: {
loaders: [{
test: /\.jsx?$/,
@ -45,7 +48,7 @@ module.exports = function(config) {
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
logLevel: config.LOG_INFO, // LOG_DEBUG
autoWatch: true,
browsers: ['Chrome'],
singleRun: false

@ -13,6 +13,9 @@ module.exports = function(config) {
'test/test-main.js': ['webpack']
},
webpack: {
entry: [
'./src/quagga.js'
],
module: {
loaders: [{
test: /\.jsx?$/,

@ -11,6 +11,7 @@ import EAN2Reader from '../reader/ean_2_reader';
import EAN5Reader from '../reader/ean_5_reader';
import UPCEReader from '../reader/upc_e_reader';
import I2of5Reader from '../reader/i2of5_reader';
import TwoOfFiveReader from '../reader/2of5_reader';
const READERS = {
code_128_reader: Code128Reader,
@ -23,7 +24,8 @@ const READERS = {
codabar_reader: CodabarReader,
upc_reader: UPCReader,
upc_e_reader: UPCEReader,
i2of5_reader: I2of5Reader
i2of5_reader: I2of5Reader,
'2of5_reader': TwoOfFiveReader,
};
export default {
create: function(config, inputImageWrapper) {

@ -14,7 +14,7 @@ function waitForVideo(video) {
function checkVideo() {
if (attempts > 0) {
if (video.videoWidth > 0 && video.videoHeight > 0) {
if (video.videoWidth > 10 && video.videoHeight > 10) {
if (ENV.development) {
console.log(video.videoWidth + "px x " + video.videoHeight + "px");
}

@ -0,0 +1,260 @@
import BarcodeReader from './barcode_reader';
function TwoOfFiveReader(opts) {
BarcodeReader.call(this, opts);
this.barSpaceRatio = [1, 1];
}
var N = 1,
W = 3,
properties = {
START_PATTERN: {value: [W, N, W, N, N, N]},
STOP_PATTERN: {value: [W, N, N, N, W]},
CODE_PATTERN: {value: [
[N, N, W, W, N],
[W, N, N, N, W],
[N, W, N, N, W],
[W, W, N, N, N],
[N, N, W, N, W],
[W, N, W, N, N],
[N, W, W, N, N],
[N, N, N, W, W],
[W, N, N, W, N],
[N, W, N, W, N]
]},
SINGLE_CODE_ERROR: {value: 0.78, writable: true},
AVG_CODE_ERROR: {value: 0.30, writable: true},
MAX_CORRECTION_FACTOR: {value: 5},
FORMAT: {value: "2of5"}
};
const startPatternLength = properties.START_PATTERN.value.reduce((sum, val) => sum + val, 0);
TwoOfFiveReader.prototype = Object.create(BarcodeReader.prototype, properties);
TwoOfFiveReader.prototype.constructor = TwoOfFiveReader;
TwoOfFiveReader.prototype._findPattern = function(pattern, offset, isWhite, tryHarder) {
var counter = [],
self = this,
i,
counterPos = 0,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: 0,
end: 0
},
error,
j,
sum,
normalized,
epsilon = self.AVG_CODE_ERROR;
isWhite = isWhite || false;
tryHarder = tryHarder || false;
if (!offset) {
offset = self._nextSet(self._row);
}
for ( i = 0; i < pattern.length; i++) {
counter[i] = 0;
}
for ( i = offset; i < self._row.length; i++) {
if (self._row[i] ^ isWhite) {
counter[counterPos]++;
} else {
if (counterPos === counter.length - 1) {
sum = 0;
for ( j = 0; j < counter.length; j++) {
sum += counter[j];
}
error = self._matchPattern(counter, pattern);
if (error < epsilon) {
bestMatch.error = error;
bestMatch.start = i - sum;
bestMatch.end = i;
return bestMatch;
}
if (tryHarder) {
for (j = 0; j < counter.length - 2; j++) {
counter[j] = counter[j + 2];
}
counter[counter.length - 2] = 0;
counter[counter.length - 1] = 0;
counterPos--;
} else {
return null;
}
} else {
counterPos++;
}
counter[counterPos] = 1;
isWhite = !isWhite;
}
}
return null;
};
TwoOfFiveReader.prototype._findStart = function() {
var self = this,
leadingWhitespaceStart,
offset = self._nextSet(self._row),
startInfo,
narrowBarWidth = 1;
while (!startInfo) {
startInfo = self._findPattern(self.START_PATTERN, offset, false, true);
if (!startInfo) {
return null;
}
narrowBarWidth = Math.floor((startInfo.end - startInfo.start) / startPatternLength);
leadingWhitespaceStart = startInfo.start - narrowBarWidth * 5;
if (leadingWhitespaceStart >= 0) {
if (self._matchRange(leadingWhitespaceStart, startInfo.start, 0)) {
return startInfo;
}
}
offset = startInfo.end;
startInfo = null;
}
};
TwoOfFiveReader.prototype._verifyTrailingWhitespace = function(endInfo) {
var self = this,
trailingWhitespaceEnd;
trailingWhitespaceEnd = endInfo.end + ((endInfo.end - endInfo.start) / 2);
if (trailingWhitespaceEnd < self._row.length) {
if (self._matchRange(endInfo.end, trailingWhitespaceEnd, 0)) {
return endInfo;
}
}
return null;
};
TwoOfFiveReader.prototype._findEnd = function() {
var self = this,
endInfo,
tmp,
offset;
self._row.reverse();
offset = self._nextSet(self._row);
endInfo = self._findPattern(self.STOP_PATTERN, offset, false, true);
self._row.reverse();
if (endInfo === null) {
return null;
}
// reverse numbers
tmp = endInfo.start;
endInfo.start = self._row.length - endInfo.end;
endInfo.end = self._row.length - tmp;
return endInfo !== null ? self._verifyTrailingWhitespace(endInfo) : null;
};
TwoOfFiveReader.prototype._decodeCode = function(counter) {
var j,
self = this,
sum = 0,
normalized,
error,
epsilon = self.AVG_CODE_ERROR,
code,
bestMatch = {
error: Number.MAX_VALUE,
code: -1,
start: 0,
end: 0
};
for ( j = 0; j < counter.length; j++) {
sum += counter[j];
}
for (code = 0; code < self.CODE_PATTERN.length; code++) {
error = self._matchPattern(counter, self.CODE_PATTERN[code]);
if (error < bestMatch.error) {
bestMatch.code = code;
bestMatch.error = error;
}
}
if (bestMatch.error < epsilon) {
return bestMatch;
}
};
TwoOfFiveReader.prototype._decodePayload = function(counters, result, decodedCodes) {
var i,
self = this,
pos = 0,
counterLength = counters.length,
counter = [0, 0, 0, 0, 0],
code;
while (pos < counterLength) {
for (i = 0; i < 5; i++) {
counter[i] = counters[pos] * this.barSpaceRatio[0];
pos += 2;
}
code = self._decodeCode(counter);
if (!code) {
return null;
}
result.push(code.code + "");
decodedCodes.push(code);
}
return code;
};
TwoOfFiveReader.prototype._verifyCounterLength = function(counters) {
return (counters.length % 10 === 0);
};
TwoOfFiveReader.prototype._decode = function() {
var startInfo,
endInfo,
self = this,
code,
result = [],
decodedCodes = [],
counters;
startInfo = self._findStart();
if (!startInfo) {
return null;
}
decodedCodes.push(startInfo);
endInfo = self._findEnd();
if (!endInfo) {
return null;
}
counters = self._fillCounters(startInfo.end, endInfo.start, false);
if (!self._verifyCounterLength(counters)) {
return null;
}
code = self._decodePayload(counters, result, decodedCodes);
if (!code) {
return null;
}
if (result.length % 2 !== 0 ||
result.length < 6) {
return null;
}
decodedCodes.push(endInfo);
return {
code: result.join(""),
start: startInfo.start,
end: endInfo.end,
startInfo: startInfo,
decodedCodes: decodedCodes
};
};
export default TwoOfFiveReader;

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

@ -304,4 +304,41 @@ describe('decodeSingle', function () {
});
_runTestSet(testSet, config);
});
describe("2of5", function() {
var config = config = {
inputStream: {
size: 800,
singleChannel: false
},
locator: {
patchSize: "medium",
halfSample: true
},
numOfWorkers: 0,
decoder: {
readers: ["2of5_reader"]
},
locate: true,
src: null
},
testSet = [
{"name": "image-001.jpg", "result": "9577149002"},
{"name": "image-002.jpg", "result": "9577149002"},
{"name": "image-003.jpg", "result": "5776158811"},
{"name": "image-004.jpg", "result": "0463381455"},
{"name": "image-005.jpg", "result": "3261594101"},
{"name": "image-006.jpg", "result": "3261594101"},
{"name": "image-007.jpg", "result": "3261594101"},
{"name": "image-008.jpg", "result": "6730705801"},
{"name": "image-009.jpg", "result": "5776158811"},
{"name": "image-010.jpg", "result": "5776158811"}
];
testSet.forEach(function(sample) {
sample.format = "2of5";
});
_runTestSet(testSet, config);
});
});

@ -153,21 +153,6 @@ describe("camera_access", () => {
done();
});
});
it("should set deviceId if facingMode is set to environment", (done) => {
setDevices([{deviceId: "front", kind: "videoinput", label: "front Facing"},
{deviceId: "back", label: "back Facing", kind: "videoinput"}]);
const givenConstraints = {width: 180, facingMode: "environment"};
return pickConstraints(givenConstraints).then((actualConstraints) => {
expect(actualConstraints.video).to.deep.equal({width: 180, deviceId: "back"});
done();
})
.catch((err) => {
console.log(err);
expect(err).to.equal(null);
done();
});
});
});
});
});

Loading…
Cancel
Save