mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-13 05:31:37 +08:00
Updated to 0.6.10
This commit is contained in:
+121
-15
@@ -4815,14 +4815,20 @@ define('cv_utils',['cluster', 'glMatrixAddon', "array_helper"], function(Cluster
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CVUtils.computeGray = function(imageData, outArray) {
|
CVUtils.computeGray = function(imageData, outArray, config) {
|
||||||
var l = imageData.length / 4;
|
var l = (imageData.length / 4) | 0,
|
||||||
var i = 0;
|
i,
|
||||||
for ( i = 0; i < l; i++) {
|
singleChannel = config && config.singleChannel === true;
|
||||||
//outArray[i] = (0.299*imageData[i*4+0] + 0.587*imageData[i*4+1] + 0.114*imageData[i*4+2]);
|
|
||||||
|
|
||||||
|
if (singleChannel) {
|
||||||
|
for (i = 0; i < l; i++) {
|
||||||
|
outArray[i] = imageData[i * 4 + 0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; i < l; i++) {
|
||||||
outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]);
|
outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CVUtils.loadImageArray = function(src, callback, canvas) {
|
CVUtils.loadImageArray = function(src, callback, canvas) {
|
||||||
@@ -6003,6 +6009,26 @@ define('image_debug',[],function() {
|
|||||||
}
|
}
|
||||||
ctx.closePath();
|
ctx.closePath();
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
},
|
||||||
|
drawImage: function(imageData, size, ctx) {
|
||||||
|
var canvasData = ctx.getImageData(0, 0, size.x, size.y),
|
||||||
|
data = canvasData.data,
|
||||||
|
imageDataPos = imageData.length,
|
||||||
|
canvasDataPos = data.length,
|
||||||
|
value;
|
||||||
|
|
||||||
|
if (canvasDataPos/imageDataPos !== 4) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while(imageDataPos--){
|
||||||
|
value = imageData[imageDataPos];
|
||||||
|
data[--canvasDataPos] = 255;
|
||||||
|
data[--canvasDataPos] = value;
|
||||||
|
data[--canvasDataPos] = value;
|
||||||
|
data[--canvasDataPos] = value;
|
||||||
|
}
|
||||||
|
ctx.putImageData(canvasData, 0, 0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -7939,7 +7965,7 @@ define('frame_grabber',["cv_utils"], function(CVUtils) {
|
|||||||
if(doHalfSample){
|
if(doHalfSample){
|
||||||
CVUtils.grayAndHalfSampleFromCanvasData(ctxData, _size, _data);
|
CVUtils.grayAndHalfSampleFromCanvasData(ctxData, _size, _data);
|
||||||
} else {
|
} else {
|
||||||
CVUtils.computeGray(ctxData, _data);
|
CVUtils.computeGray(ctxData, _data, _streamConfig);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -8017,7 +8043,8 @@ define('config',[],function(){
|
|||||||
right: "0%",
|
right: "0%",
|
||||||
left: "0%",
|
left: "0%",
|
||||||
bottom: "0%"
|
bottom: "0%"
|
||||||
}
|
},
|
||||||
|
singleChannel: false // true: only the red color-channel is read
|
||||||
},
|
},
|
||||||
tracking: false,
|
tracking: false,
|
||||||
debug: false,
|
debug: false,
|
||||||
@@ -8288,6 +8315,66 @@ define('camera_access',["html_utils"], function(HtmlUtils) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||||
|
/* global define */
|
||||||
|
|
||||||
|
define('result_collector',["image_debug"], function(ImageDebug) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function contains(codeResult, list) {
|
||||||
|
if (list) {
|
||||||
|
return list.some(function (item) {
|
||||||
|
return Object.keys(item).every(function (key) {
|
||||||
|
return item[key] === codeResult[key];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function passesFilter(codeResult, filter) {
|
||||||
|
if (typeof filter === 'function') {
|
||||||
|
return filter(codeResult);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
create: function(config) {
|
||||||
|
var canvas = document.createElement("canvas"),
|
||||||
|
ctx = canvas.getContext("2d"),
|
||||||
|
results = [],
|
||||||
|
capacity = config.capacity || 20,
|
||||||
|
capture = config.capture === true;
|
||||||
|
|
||||||
|
function matchesConstraints(codeResult) {
|
||||||
|
return capacity && codeResult && !contains(codeResult, config.blacklist) && passesFilter(codeResult, config.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
addResult: function(data, imageSize, codeResult) {
|
||||||
|
var result = {};
|
||||||
|
|
||||||
|
if (matchesConstraints(codeResult)) {
|
||||||
|
capacity--;
|
||||||
|
result.codeResult = codeResult;
|
||||||
|
if (capture) {
|
||||||
|
canvas.width = imageSize.x;
|
||||||
|
canvas.height = imageSize.y;
|
||||||
|
ImageDebug.drawImage(data, imageSize, ctx);
|
||||||
|
result.frame = canvas.toDataURL();
|
||||||
|
}
|
||||||
|
results.push(result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getResults: function() {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
|
||||||
@@ -8304,7 +8391,8 @@ define('quagga',[
|
|||||||
"config",
|
"config",
|
||||||
"events",
|
"events",
|
||||||
"camera_access",
|
"camera_access",
|
||||||
"image_debug"],
|
"image_debug",
|
||||||
|
"result_collector"],
|
||||||
function(Code128Reader,
|
function(Code128Reader,
|
||||||
EANReader,
|
EANReader,
|
||||||
InputStream,
|
InputStream,
|
||||||
@@ -8316,7 +8404,8 @@ function(Code128Reader,
|
|||||||
_config,
|
_config,
|
||||||
Events,
|
Events,
|
||||||
CameraAccess,
|
CameraAccess,
|
||||||
ImageDebug) {
|
ImageDebug,
|
||||||
|
ResultCollector) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _inputStream,
|
var _inputStream,
|
||||||
@@ -8336,7 +8425,8 @@ function(Code128Reader,
|
|||||||
_boxSize,
|
_boxSize,
|
||||||
_decoder,
|
_decoder,
|
||||||
_workerPool = [],
|
_workerPool = [],
|
||||||
_onUIThread = true;
|
_onUIThread = true,
|
||||||
|
_resultCollector;
|
||||||
|
|
||||||
function initializeData(imageWrapper) {
|
function initializeData(imageWrapper) {
|
||||||
initBuffers(imageWrapper);
|
initBuffers(imageWrapper);
|
||||||
@@ -8344,6 +8434,7 @@ function(Code128Reader,
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initConfig() {
|
function initConfig() {
|
||||||
|
if (typeof document !== "undefined") {
|
||||||
var vis = [{
|
var vis = [{
|
||||||
node: document.querySelector("div[data-controls]"),
|
node: document.querySelector("div[data-controls]"),
|
||||||
prop: _config.controls
|
prop: _config.controls
|
||||||
@@ -8362,6 +8453,7 @@ function(Code128Reader,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function initInputStream(cb) {
|
function initInputStream(cb) {
|
||||||
var video;
|
var video;
|
||||||
@@ -8420,6 +8512,7 @@ function(Code128Reader,
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initCanvas() {
|
function initCanvas() {
|
||||||
|
if (typeof document !== "undefined") {
|
||||||
var $viewport = document.querySelector("#interactive.viewport");
|
var $viewport = document.querySelector("#interactive.viewport");
|
||||||
_canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
|
_canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
|
||||||
if (!_canvasContainer.dom.image) {
|
if (!_canvasContainer.dom.image) {
|
||||||
@@ -8450,6 +8543,7 @@ function(Code128Reader,
|
|||||||
_canvasContainer.dom.overlay.width = _inputStream.getCanvasSize().x;
|
_canvasContainer.dom.overlay.width = _inputStream.getCanvasSize().x;
|
||||||
_canvasContainer.dom.overlay.height = _inputStream.getCanvasSize().y;
|
_canvasContainer.dom.overlay.height = _inputStream.getCanvasSize().y;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function initBuffers(imageWrapper) {
|
function initBuffers(imageWrapper) {
|
||||||
if (imageWrapper) {
|
if (imageWrapper) {
|
||||||
@@ -8516,10 +8610,16 @@ function(Code128Reader,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function publishResult(result) {
|
function publishResult(result, imageData) {
|
||||||
if (_onUIThread) {
|
if (_onUIThread) {
|
||||||
transformResult(result);
|
transformResult(result);
|
||||||
|
if (imageData && result && result.codeResult) {
|
||||||
|
if (_resultCollector) {
|
||||||
|
_resultCollector.addResult(imageData, _inputStream.getCanvasSize(), result.codeResult);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Events.publish("processed", result);
|
Events.publish("processed", result);
|
||||||
if (result && result.codeResult) {
|
if (result && result.codeResult) {
|
||||||
Events.publish("detected", result);
|
Events.publish("detected", result);
|
||||||
@@ -8535,7 +8635,7 @@ function(Code128Reader,
|
|||||||
result = _decoder.decodeFromBoundingBoxes(boxes);
|
result = _decoder.decodeFromBoundingBoxes(boxes);
|
||||||
result = result || {};
|
result = result || {};
|
||||||
result.boxes = boxes;
|
result.boxes = boxes;
|
||||||
publishResult(result);
|
publishResult(result, _inputImageWrapper.data);
|
||||||
} else {
|
} else {
|
||||||
publishResult();
|
publishResult();
|
||||||
}
|
}
|
||||||
@@ -8604,7 +8704,7 @@ function(Code128Reader,
|
|||||||
function initWorker(cb) {
|
function initWorker(cb) {
|
||||||
var blobURL,
|
var blobURL,
|
||||||
workerThread = {
|
workerThread = {
|
||||||
worker: null,
|
worker: undefined,
|
||||||
imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()),
|
imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()),
|
||||||
busy: true
|
busy: true
|
||||||
};
|
};
|
||||||
@@ -8622,7 +8722,7 @@ function(Code128Reader,
|
|||||||
} else if (e.data.event === 'processed') {
|
} else if (e.data.event === 'processed') {
|
||||||
workerThread.imageData = new Uint8Array(e.data.imageData);
|
workerThread.imageData = new Uint8Array(e.data.imageData);
|
||||||
workerThread.busy = false;
|
workerThread.busy = false;
|
||||||
publishResult(e.data.result);
|
publishResult(e.data.result, workerThread.imageData);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -8737,6 +8837,11 @@ function(Code128Reader,
|
|||||||
setReaders: function(readers) {
|
setReaders: function(readers) {
|
||||||
setReaders(readers);
|
setReaders(readers);
|
||||||
},
|
},
|
||||||
|
registerResultCollector: function(resultCollector) {
|
||||||
|
if (resultCollector && typeof resultCollector.addResult === 'function') {
|
||||||
|
_resultCollector = resultCollector;
|
||||||
|
}
|
||||||
|
},
|
||||||
canvas : _canvasContainer,
|
canvas : _canvasContainer,
|
||||||
decodeSingle : function(config, resultCallback) {
|
decodeSingle : function(config, resultCallback) {
|
||||||
config = HtmlUtils.mergeObjects({
|
config = HtmlUtils.mergeObjects({
|
||||||
@@ -8764,7 +8869,8 @@ function(Code128Reader,
|
|||||||
Code128Reader : Code128Reader
|
Code128Reader : Code128Reader
|
||||||
},
|
},
|
||||||
ImageWrapper: ImageWrapper,
|
ImageWrapper: ImageWrapper,
|
||||||
ImageDebug: ImageDebug
|
ImageDebug: ImageDebug,
|
||||||
|
ResultCollector: ResultCollector
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Vendored
+4
-4
File diff suppressed because one or more lines are too long
@@ -7,7 +7,7 @@ showInMenu: true
|
|||||||
quaggaJS
|
quaggaJS
|
||||||
========
|
========
|
||||||
|
|
||||||
- [Changelog](#changelog) (2015-06-14)
|
- [Changelog](#changelog) (2015-06-21)
|
||||||
|
|
||||||
## What is QuaggaJS?
|
## What is QuaggaJS?
|
||||||
|
|
||||||
@@ -223,7 +223,14 @@ The default `config` object is set as followed:
|
|||||||
width: 640,
|
width: 640,
|
||||||
height: 480,
|
height: 480,
|
||||||
facing: "environment"
|
facing: "environment"
|
||||||
}
|
},
|
||||||
|
area: { // defines rectangle of the detection/localization area
|
||||||
|
top: "0%", // top offset
|
||||||
|
right: "0%", // right offset
|
||||||
|
left: "0%", // left offset
|
||||||
|
bottom: "0%" // bottom offset
|
||||||
|
},
|
||||||
|
singleChannel: false // true: only the red color-channel is read
|
||||||
},
|
},
|
||||||
tracking: false,
|
tracking: false,
|
||||||
debug: false,
|
debug: false,
|
||||||
@@ -297,8 +304,71 @@ web-workers, and their restriction not to have access to the DOM, the
|
|||||||
configuration must be explicitly set to `config.numOfWorkers = 0` in order to
|
configuration must be explicitly set to `config.numOfWorkers = 0` in order to
|
||||||
work.
|
work.
|
||||||
|
|
||||||
|
## <a name="resultcollector">ResultCollector</a>
|
||||||
|
|
||||||
|
Quagga is not perfect by any means and may produce false positives from time
|
||||||
|
to time. In order to find out which images produced those false positives,
|
||||||
|
the built-in ``ResultCollector`` will support you and me helping squashing
|
||||||
|
bugs in the implementation.
|
||||||
|
|
||||||
|
### Creating a ``ResultCollector``
|
||||||
|
|
||||||
|
You can easily create a new ``ResultCollector`` by calling its ``create``
|
||||||
|
method with a configuration.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var resultCollector = Quagga.ResultCollector.create({
|
||||||
|
capture: true, // keep track of the image producing this result
|
||||||
|
capacity: 20, // maximum number of results to store
|
||||||
|
blacklist: [ // list containing codes which should not be recorded
|
||||||
|
{code: "3574660239843", format: "ean_13"}],
|
||||||
|
filter: function(codeResult) {
|
||||||
|
// only store results which match this constraint
|
||||||
|
// returns true/false
|
||||||
|
// e.g.: return codeResult.format === "ean_13";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using a ``ResultCollector``
|
||||||
|
|
||||||
|
After creating a ``ResultCollector`` you have to attach it to Quagga by
|
||||||
|
calling ``Quagga.registerResultCollector(resultCollector)``.
|
||||||
|
|
||||||
|
### Reading results
|
||||||
|
|
||||||
|
After a test/recording session, you can now print the collected results which
|
||||||
|
do not fit into a certain schema. Calling ``getResults`` on the
|
||||||
|
``resultCollector`` returns an ``Array`` containing objects with:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
codeResult: {}, // same as in onDetected event
|
||||||
|
frame: "data:image/png;base64,iVBOR..." // dataURL of the gray-scaled image
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The ``frame`` property is an internal representation of the image and
|
||||||
|
therefore only available in gray-scale. The dataURL representation allows
|
||||||
|
easy saving/rendering of the image.
|
||||||
|
|
||||||
|
### Comparing results
|
||||||
|
|
||||||
|
Now, having the frames available on disk, you can load each single image by
|
||||||
|
calling ``decodeSingle`` with the same configuration as used during recording
|
||||||
|
. In order to reproduce the exact same result, you have to make sure to turn
|
||||||
|
on the ``singleChannel`` flag in the configuration when using ``decodeSingle``.
|
||||||
|
|
||||||
## <a name="changelog">Changelog</a>
|
## <a name="changelog">Changelog</a>
|
||||||
|
|
||||||
|
### 2015-06-21
|
||||||
|
- Features
|
||||||
|
- Added ``singleChannel`` configuration to ``inputStream`` (in [config]
|
||||||
|
(#configobject))
|
||||||
|
- Added ``ResultCollector`` functionality (see [ResultCollector]
|
||||||
|
(#resultcollector))
|
||||||
|
|
||||||
### 2015-06-14
|
### 2015-06-14
|
||||||
- Improvements
|
- Improvements
|
||||||
- Added ``format`` property to ``codeResult`` (in [result](#resultobject))
|
- Added ``format`` property to ``codeResult`` (in [result](#resultobject))
|
||||||
|
|||||||
Reference in New Issue
Block a user