Another try on web-workers; works with decoding single-images only; live-stream and video-input won't work

pull/12/head
Christoph Oberhofer 11 years ago
parent ebceb1f78c
commit 72940990d3

1
.gitignore vendored

@ -3,3 +3,4 @@ node_modules/
coverage/ coverage/
.project .project
_site/ _site/
.idea/

@ -21,7 +21,7 @@ module.exports = function(grunt) {
all : ['Gruntfile.js', 'src/*.js'] all : ['Gruntfile.js', 'src/*.js']
}, },
requirejs : { requirejs : {
compile : { quagga : {
options : { options : {
almond : true, almond : true,
wrap : { wrap : {
@ -51,6 +51,41 @@ module.exports = function(grunt) {
} }
}, },
"paths" : {
"typedefs" : "typedefs",
"glMatrix" : "vendor/glMatrix",
"glMatrixAddon" : "glMatrixAddon"
}
}
},
locator : {
options : {
almond : true,
wrap : {
startFile : 'build/locator_start.frag',
endFile : 'build/locator_end.frag'
},
"baseUrl" : "src",
"name" : "barcode_locator",
"out" : "dist/locator.js",
"include" : ['barcode_locator'],
"optimize" : "none",
"findNestedDependencies" : true,
"skipSemiColonInsertion" : true,
"shim" : {
"typedefs" : {
"deps" : [],
"exports" : "typedefs"
},
"glMatrix" : {
"deps" : ["typedefs"],
"exports" : "glMatrix"
},
"glMatrixAddon" : {
"deps" : ["glMatrix"],
"exports" : "glMatrixAddon"
}
},
"paths" : { "paths" : {
"typedefs" : "typedefs", "typedefs" : "typedefs",
"glMatrix" : "vendor/glMatrix", "glMatrix" : "vendor/glMatrix",
@ -68,7 +103,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-requirejs'); grunt.loadNpmTasks('grunt-requirejs');
grunt.loadNpmTasks('grunt-karma'); grunt.loadNpmTasks('grunt-karma');
// Default task(s). // Default task(s).
grunt.registerTask('default', ['jshint', 'requirejs', 'uglify']); grunt.registerTask('default', ['jshint', 'requirejs']);
grunt.registerTask('test', ['karma']); grunt.registerTask('test', ['karma']);
}; };

@ -0,0 +1,2 @@
return require('barcode_locator');
}));

@ -0,0 +1,13 @@
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
//Allow using this built library as an AMD module
//in another project. That other project will only
//see this AMD call, not the internal modules in
//the closure below.
define([], factory);
} else {
//Browser globals case. Just assign the
//result to a property on the global.
root.Locator = factory();
}
}(this, function () {

5069
dist/locator.js vendored

File diff suppressed because it is too large Load Diff

189
dist/quagga.js vendored

@ -1621,21 +1621,22 @@ define('input_stream',["image_loader"], function(ImageLoader) {
*/ */
glMatrixArrayType = Float32Array; glMatrixArrayType = Float32Array;
if (typeof window !== 'undefined') {
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000 / 60);
};
})();
window.requestAnimFrame = (function() { navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
return window.requestAnimationFrame || window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
window.webkitRequestAnimationFrame || }
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000/60);
};
})();
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
define("typedefs", (function (global) { define("typedefs", (function (global) {
return function () { return function () {
var ret, fn; var ret, fn;
@ -5720,7 +5721,11 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
}, },
_numPatches = {x: 0, y: 0}, _numPatches = {x: 0, y: 0},
_inputImageWrapper, _inputImageWrapper,
_skeletonizer; _skeletonizer,
self = this,
_worker,
_locatedCb,
_initialized;
function initBuffers() { function initBuffers() {
var skeletonImageData; var skeletonImageData;
@ -5746,10 +5751,10 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
_labelImageWrapper = new ImageWrapper(_patchSize, undefined, Array, true); _labelImageWrapper = new ImageWrapper(_patchSize, undefined, Array, true);
skeletonImageData = new ArrayBuffer(_patchSize.x * _patchSize.y * 16); skeletonImageData = new ArrayBuffer(64*1024);
_subImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, 0, _patchSize.x * _patchSize.y)); _subImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, 0, _patchSize.x * _patchSize.y));
_skelImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, _patchSize.x * _patchSize.y * 3, _patchSize.x * _patchSize.y), undefined, true); _skelImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, _patchSize.x * _patchSize.y * 3, _patchSize.x * _patchSize.y), undefined, true);
_skeletonizer = skeletonizer(window, { _skeletonizer = skeletonizer(self, {
size : _patchSize.x size : _patchSize.x
}, skeletonImageData); }, skeletonImageData);
@ -5762,6 +5767,9 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
} }
function initCanvas() { function initCanvas() {
if (_config.useWorker || typeof document === 'undefined') {
return;
}
_canvasContainer.dom.binary = document.createElement("canvas"); _canvasContainer.dom.binary = document.createElement("canvas");
_canvasContainer.dom.binary.className = "binaryBuffer"; _canvasContainer.dom.binary.className = "binaryBuffer";
if (_config.showCanvas === true) { if (_config.showCanvas === true) {
@ -6165,44 +6173,74 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
return label; return label;
} }
function initWorker(cb) {
var tmpData;
_worker = new Worker('../src/worker_locator.js');
tmpData = _inputImageWrapper.data;
_inputImageWrapper.data = null; // do not send the data along
_worker.postMessage({cmd: 'init', inputImageWrapper: _inputImageWrapper});
_inputImageWrapper.data = tmpData;
_worker.onmessage = function(e) {
if (e.data.event === 'initialized') {
_initialized = true;
cb();
} else if (e.data.event === 'located') {
_inputImageWrapper.data = new Uint8Array(e.data.buffer);
_locatedCb(e.data.result);
}
};
}
return { return {
init : function(config, data) { init : function(config, data, cb) {
_config = config; _config = config;
_inputImageWrapper = data.inputImageWrapper; _inputImageWrapper = data.inputImageWrapper;
initBuffers();
initCanvas(); // 1. check config for web-worker
if (_config.useWorker) {
initWorker(cb);
} else {
initBuffers();
initCanvas();
cb();
}
}, },
locate : function() { locate : function(cb) {
var patchesFound, var patchesFound,
topLabels = [], topLabels = [],
boxes = []; boxes = [];
if (_halfSample) { if (_config.useWorker) {
CVUtils.halfSample(_inputImageWrapper, _currentImageWrapper); _locatedCb = cb;
} _worker.postMessage({cmd: 'locate', buffer: _inputImageWrapper.data}, [_inputImageWrapper.data.buffer]);
} else {
binarizeImage(); if (_halfSample) {
patchesFound = findPatches(); CVUtils.halfSample(_inputImageWrapper, _currentImageWrapper);
// return unless 5% or more patches are found }
if (patchesFound.length < _numPatches.x * _numPatches.y * 0.05) {
return; binarizeImage();
} patchesFound = findPatches();
// return unless 5% or more patches are found
// rasterrize area by comparing angular similarity; if (patchesFound.length < _numPatches.x * _numPatches.y * 0.05) {
var maxLabel = rasterizeAngularSimilarity(patchesFound); return cb(null);
if (maxLabel <= 1) { }
return null;
} // rasterrize area by comparing angular similarity;
var maxLabel = rasterizeAngularSimilarity(patchesFound);
// search for area with the most patches (biggest connected area) if (maxLabel <= 1) {
topLabels = findBiggestConnectedAreas(maxLabel); return cb(null);
if (topLabels.length === 0) { }
return null;
// search for area with the most patches (biggest connected area)
topLabels = findBiggestConnectedAreas(maxLabel);
if (topLabels.length === 0) {
return cb(null);
}
boxes = findBoxes(topLabels, maxLabel);
cb(boxes);
} }
boxes = findBoxes(topLabels, maxLabel);
return boxes;
} }
}; };
}); });
@ -6820,6 +6858,7 @@ define('config',[],function(){
] ]
}, },
locator: { locator: {
useWorker: true,
showCanvas: false, showCanvas: false,
showPatches: false, showPatches: false,
showFoundPatches: false, showFoundPatches: false,
@ -7111,18 +7150,19 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
} }
function canRecord() { function canRecord() {
initBuffers(); initBuffers(function() {
initCanvas(); initCanvas();
_decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper); _decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper);
_framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image); _framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image);
_framegrabber.attachData(_inputImageWrapper.data); _framegrabber.attachData(_inputImageWrapper.data);
initConfig(); initConfig();
_inputStream.play(); _inputStream.play();
_initialized = true; _initialized = true;
if (_config.readyFunc) { if (_config.readyFunc) {
_config.readyFunc.apply(); _config.readyFunc.apply();
} }
});
} }
function initCanvas() { function initCanvas() {
@ -7157,7 +7197,7 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
_canvasContainer.dom.overlay.height = _inputImageWrapper.size.y; _canvasContainer.dom.overlay.height = _inputImageWrapper.size.y;
} }
function initBuffers() { function initBuffers(cb) {
_inputImageWrapper = new ImageWrapper({ _inputImageWrapper = new ImageWrapper({
x : _inputStream.getWidth(), x : _inputStream.getWidth(),
y : _inputStream.getHeight() y : _inputStream.getHeight()
@ -7170,35 +7210,34 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 + 100]), vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 + 100]),
vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 - 100]) vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 - 100])
]; ];
BarcodeLocator.init(_config.locator, { BarcodeLocator.init(_config.locator, {inputImageWrapper : _inputImageWrapper}, cb);
inputImageWrapper : _inputImageWrapper
});
} }
function getBoundingBoxes() { function getBoundingBoxes(cb) {
var boxes;
if (_config.locate) { if (_config.locate) {
boxes = BarcodeLocator.locate(); BarcodeLocator.locate(cb);
} else { } else {
boxes = [_boxSize]; cb([_boxSize]);
} }
return boxes;
} }
function update() { function update() {
var result, var result;
boxes;
if (_framegrabber.grab()) { if (_framegrabber.grab()) {
_canvasContainer.ctx.overlay.clearRect(0, 0, _inputImageWrapper.size.x, _inputImageWrapper.size.y); _canvasContainer.ctx.overlay.clearRect(0, 0, _inputImageWrapper.size.x, _inputImageWrapper.size.y);
boxes = getBoundingBoxes(); console.time("getBoundingBoxes");
if (boxes) { getBoundingBoxes(function(boxes) {
result = _decoder.decodeFromBoundingBoxes(boxes); console.timeEnd("getBoundingBoxes");
if (result && result.codeResult) { // attach data back to grabber
Events.publish("detected", result.codeResult.code); _framegrabber.attachData(_inputImageWrapper.data);
if (boxes) {
result = _decoder.decodeFromBoundingBoxes(boxes);
if (result && result.codeResult) {
Events.publish("detected", result.codeResult.code);
}
} }
} });
} }
} }

@ -26,7 +26,11 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
}, },
_numPatches = {x: 0, y: 0}, _numPatches = {x: 0, y: 0},
_inputImageWrapper, _inputImageWrapper,
_skeletonizer; _skeletonizer,
self = this,
_worker,
_locatedCb,
_initialized;
function initBuffers() { function initBuffers() {
var skeletonImageData; var skeletonImageData;
@ -52,10 +56,10 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
_labelImageWrapper = new ImageWrapper(_patchSize, undefined, Array, true); _labelImageWrapper = new ImageWrapper(_patchSize, undefined, Array, true);
skeletonImageData = new ArrayBuffer(_patchSize.x * _patchSize.y * 16); skeletonImageData = new ArrayBuffer(64*1024);
_subImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, 0, _patchSize.x * _patchSize.y)); _subImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, 0, _patchSize.x * _patchSize.y));
_skelImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, _patchSize.x * _patchSize.y * 3, _patchSize.x * _patchSize.y), undefined, true); _skelImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, _patchSize.x * _patchSize.y * 3, _patchSize.x * _patchSize.y), undefined, true);
_skeletonizer = skeletonizer(window, { _skeletonizer = skeletonizer(self, {
size : _patchSize.x size : _patchSize.x
}, skeletonImageData); }, skeletonImageData);
@ -68,6 +72,9 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
} }
function initCanvas() { function initCanvas() {
if (_config.useWorker || typeof document === 'undefined') {
return;
}
_canvasContainer.dom.binary = document.createElement("canvas"); _canvasContainer.dom.binary = document.createElement("canvas");
_canvasContainer.dom.binary.className = "binaryBuffer"; _canvasContainer.dom.binary.className = "binaryBuffer";
if (_config.showCanvas === true) { if (_config.showCanvas === true) {
@ -471,44 +478,74 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
return label; return label;
} }
function initWorker(cb) {
var tmpData;
_worker = new Worker('../src/worker_locator.js');
tmpData = _inputImageWrapper.data;
_inputImageWrapper.data = null; // do not send the data along
_worker.postMessage({cmd: 'init', inputImageWrapper: _inputImageWrapper});
_inputImageWrapper.data = tmpData;
_worker.onmessage = function(e) {
if (e.data.event === 'initialized') {
_initialized = true;
cb();
} else if (e.data.event === 'located') {
_inputImageWrapper.data = new Uint8Array(e.data.buffer);
_locatedCb(e.data.result);
}
};
}
return { return {
init : function(config, data) { init : function(config, data, cb) {
_config = config; _config = config;
_inputImageWrapper = data.inputImageWrapper; _inputImageWrapper = data.inputImageWrapper;
initBuffers();
initCanvas(); // 1. check config for web-worker
if (_config.useWorker) {
initWorker(cb);
} else {
initBuffers();
initCanvas();
cb();
}
}, },
locate : function() { locate : function(cb) {
var patchesFound, var patchesFound,
topLabels = [], topLabels = [],
boxes = []; boxes = [];
if (_halfSample) { if (_config.useWorker) {
CVUtils.halfSample(_inputImageWrapper, _currentImageWrapper); _locatedCb = cb;
} _worker.postMessage({cmd: 'locate', buffer: _inputImageWrapper.data}, [_inputImageWrapper.data.buffer]);
} else {
binarizeImage(); if (_halfSample) {
patchesFound = findPatches(); CVUtils.halfSample(_inputImageWrapper, _currentImageWrapper);
// return unless 5% or more patches are found }
if (patchesFound.length < _numPatches.x * _numPatches.y * 0.05) {
return; binarizeImage();
} patchesFound = findPatches();
// return unless 5% or more patches are found
// rasterrize area by comparing angular similarity; if (patchesFound.length < _numPatches.x * _numPatches.y * 0.05) {
var maxLabel = rasterizeAngularSimilarity(patchesFound); return cb(null);
if (maxLabel <= 1) { }
return null;
} // rasterrize area by comparing angular similarity;
var maxLabel = rasterizeAngularSimilarity(patchesFound);
// search for area with the most patches (biggest connected area) if (maxLabel <= 1) {
topLabels = findBiggestConnectedAreas(maxLabel); return cb(null);
if (topLabels.length === 0) { }
return null;
// search for area with the most patches (biggest connected area)
topLabels = findBiggestConnectedAreas(maxLabel);
if (topLabels.length === 0) {
return cb(null);
}
boxes = findBoxes(topLabels, maxLabel);
cb(boxes);
} }
boxes = findBoxes(topLabels, maxLabel);
return boxes;
} }
}; };
}); });

@ -24,6 +24,7 @@ define(function(){
] ]
}, },
locator: { locator: {
useWorker: true,
showCanvas: false, showCanvas: false,
showPatches: false, showPatches: false,
showFoundPatches: false, showFoundPatches: false,

@ -78,18 +78,19 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
} }
function canRecord() { function canRecord() {
initBuffers(); initBuffers(function() {
initCanvas(); initCanvas();
_decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper); _decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper);
_framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image); _framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image);
_framegrabber.attachData(_inputImageWrapper.data); _framegrabber.attachData(_inputImageWrapper.data);
initConfig(); initConfig();
_inputStream.play(); _inputStream.play();
_initialized = true; _initialized = true;
if (_config.readyFunc) { if (_config.readyFunc) {
_config.readyFunc.apply(); _config.readyFunc.apply();
} }
});
} }
function initCanvas() { function initCanvas() {
@ -124,7 +125,7 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
_canvasContainer.dom.overlay.height = _inputImageWrapper.size.y; _canvasContainer.dom.overlay.height = _inputImageWrapper.size.y;
} }
function initBuffers() { function initBuffers(cb) {
_inputImageWrapper = new ImageWrapper({ _inputImageWrapper = new ImageWrapper({
x : _inputStream.getWidth(), x : _inputStream.getWidth(),
y : _inputStream.getHeight() y : _inputStream.getHeight()
@ -137,35 +138,34 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 + 100]), vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 + 100]),
vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 - 100]) vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 - 100])
]; ];
BarcodeLocator.init(_config.locator, { BarcodeLocator.init(_config.locator, {inputImageWrapper : _inputImageWrapper}, cb);
inputImageWrapper : _inputImageWrapper
});
} }
function getBoundingBoxes() { function getBoundingBoxes(cb) {
var boxes;
if (_config.locate) { if (_config.locate) {
boxes = BarcodeLocator.locate(); BarcodeLocator.locate(cb);
} else { } else {
boxes = [_boxSize]; cb([_boxSize]);
} }
return boxes;
} }
function update() { function update() {
var result, var result;
boxes;
if (_framegrabber.grab()) { if (_framegrabber.grab()) {
_canvasContainer.ctx.overlay.clearRect(0, 0, _inputImageWrapper.size.x, _inputImageWrapper.size.y); _canvasContainer.ctx.overlay.clearRect(0, 0, _inputImageWrapper.size.x, _inputImageWrapper.size.y);
boxes = getBoundingBoxes(); console.time("getBoundingBoxes");
if (boxes) { getBoundingBoxes(function(boxes) {
result = _decoder.decodeFromBoundingBoxes(boxes); console.timeEnd("getBoundingBoxes");
if (result && result.codeResult) { // attach data back to grabber
Events.publish("detected", result.codeResult.code); _framegrabber.attachData(_inputImageWrapper.data);
if (boxes) {
result = _decoder.decodeFromBoundingBoxes(boxes);
if (result && result.codeResult) {
Events.publish("detected", result.codeResult.code);
}
} }
} });
} }
} }

@ -4,18 +4,18 @@
*/ */
glMatrixArrayType = Float32Array; glMatrixArrayType = Float32Array;
if (typeof window !== 'undefined') {
window.requestAnimFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000 / 60);
};
})();
window.requestAnimFrame = (function() { navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
return window.requestAnimationFrame || window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
window.webkitRequestAnimationFrame || }
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000/60);
};
})();
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;

@ -0,0 +1,39 @@
/* jshint undef: true, unused: true, browser:true, devel: true */
/* global importScripts, self, Locator */
importScripts('../dist/locator.js');
var inputImageWrapper = null;
self.onmessage = function(e) {
if (e.data.cmd === 'init') {
inputImageWrapper = e.data.inputImageWrapper;
init(function() {
self.postMessage({'event': 'initialized'});
});
} else if (e.data.cmd === 'locate') {
locate(new Uint8Array(e.data.buffer), function(result) {
self.postMessage({'event': 'located', result: result, buffer : inputImageWrapper.data}, [inputImageWrapper.data.buffer]);
});
}
};
function init(cb) {
Locator.init({
showCanvas: false,
showPatches: false,
showFoundPatches: false,
showSkeleton: false,
showLabels: false,
showPatchLabels: false,
showRemainingPatchLabels: false,
boxFromPatches: {
showTransformed: false,
showTransformedBox: false,
showBB: false
}
}, {
inputImageWrapper : inputImageWrapper
}, cb);
}
function locate(buffer, cb) {
inputImageWrapper.data = buffer;
Locator.locate(cb);
}
Loading…
Cancel
Save