|
|
|
@ -24,9 +24,10 @@ const mat2 = {
|
|
|
|
|
copy: require('gl-mat2/copy'),
|
|
|
|
|
create: require('gl-mat2/create'),
|
|
|
|
|
invert: require('gl-mat2/invert')
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var _config,
|
|
|
|
|
export default function createLocator(inputImageWrapper, config) {
|
|
|
|
|
var _config = config,
|
|
|
|
|
_currentImageWrapper,
|
|
|
|
|
_skelImageWrapper,
|
|
|
|
|
_subImageWrapper,
|
|
|
|
@ -45,10 +46,13 @@ var _config,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
_numPatches = {x: 0, y: 0},
|
|
|
|
|
_inputImageWrapper,
|
|
|
|
|
_inputImageWrapper = inputImageWrapper,
|
|
|
|
|
_skeletonizer;
|
|
|
|
|
|
|
|
|
|
function initBuffers() {
|
|
|
|
|
initBuffers();
|
|
|
|
|
initCanvas();
|
|
|
|
|
|
|
|
|
|
function initBuffers() {
|
|
|
|
|
var skeletonImageData;
|
|
|
|
|
|
|
|
|
|
if (_config.halfSample) {
|
|
|
|
@ -85,9 +89,9 @@ function initBuffers() {
|
|
|
|
|
}, undefined, Array, true);
|
|
|
|
|
_patchGrid = new ImageWrapper(_imageToPatchGrid.size, undefined, undefined, true);
|
|
|
|
|
_patchLabelGrid = new ImageWrapper(_imageToPatchGrid.size, undefined, Int32Array, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function initCanvas() {
|
|
|
|
|
function initCanvas() {
|
|
|
|
|
if (_config.useWorker || typeof document === 'undefined') {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -99,13 +103,13 @@ function initCanvas() {
|
|
|
|
|
_canvasContainer.ctx.binary = _canvasContainer.dom.binary.getContext("2d");
|
|
|
|
|
_canvasContainer.dom.binary.width = _binaryImageWrapper.size.x;
|
|
|
|
|
_canvasContainer.dom.binary.height = _binaryImageWrapper.size.y;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Creates a bounding box which encloses all the given patches
|
|
|
|
|
* @returns {Array} The minimal bounding box
|
|
|
|
|
*/
|
|
|
|
|
function boxFromPatches(patches) {
|
|
|
|
|
function boxFromPatches(patches) {
|
|
|
|
|
var overAvg,
|
|
|
|
|
i,
|
|
|
|
|
j,
|
|
|
|
@ -191,24 +195,24 @@ function boxFromPatches(patches) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return box;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Creates a binary image of the current image
|
|
|
|
|
*/
|
|
|
|
|
function binarizeImage() {
|
|
|
|
|
function binarizeImage() {
|
|
|
|
|
otsuThreshold(_currentImageWrapper, _binaryImageWrapper);
|
|
|
|
|
_binaryImageWrapper.zeroBorder();
|
|
|
|
|
if (ENV.development && _config.debug.showCanvas) {
|
|
|
|
|
_binaryImageWrapper.show(_canvasContainer.dom.binary, 255);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Iterate over the entire image
|
|
|
|
|
* extract patches
|
|
|
|
|
*/
|
|
|
|
|
function findPatches() {
|
|
|
|
|
function findPatches() {
|
|
|
|
|
var i,
|
|
|
|
|
j,
|
|
|
|
|
x,
|
|
|
|
@ -254,14 +258,14 @@ function findPatches() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return patchesFound;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Finds those connected areas which contain at least 6 patches
|
|
|
|
|
* and returns them ordered DESC by the number of contained patches
|
|
|
|
|
* @param {Number} maxLabel
|
|
|
|
|
*/
|
|
|
|
|
function findBiggestConnectedAreas(maxLabel){
|
|
|
|
|
function findBiggestConnectedAreas(maxLabel){
|
|
|
|
|
var i,
|
|
|
|
|
sum,
|
|
|
|
|
labelHist = [],
|
|
|
|
@ -294,12 +298,12 @@ function findBiggestConnectedAreas(maxLabel){
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return topLabels;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
function findBoxes(topLabels, maxLabel) {
|
|
|
|
|
function findBoxes(topLabels, maxLabel) {
|
|
|
|
|
var i,
|
|
|
|
|
j,
|
|
|
|
|
sum,
|
|
|
|
@ -336,13 +340,13 @@ function findBoxes(topLabels, maxLabel) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return boxes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Find similar moments (via cluster)
|
|
|
|
|
* @param {Object} moments
|
|
|
|
|
*/
|
|
|
|
|
function similarMoments(moments) {
|
|
|
|
|
function similarMoments(moments) {
|
|
|
|
|
var clusters = cluster(moments, 0.90);
|
|
|
|
|
var topCluster = topGeneric(clusters, 1, function(e) {
|
|
|
|
|
return e.getPoints().length;
|
|
|
|
@ -355,9 +359,9 @@ function similarMoments(moments) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function skeletonize(x, y) {
|
|
|
|
|
function skeletonize(x, y) {
|
|
|
|
|
_binaryImageWrapper.subImageAsCopy(_subImageWrapper, imageRef(x, y));
|
|
|
|
|
_skeletonizer.skeletonize();
|
|
|
|
|
|
|
|
|
@ -365,9 +369,9 @@ function skeletonize(x, y) {
|
|
|
|
|
if (ENV.development && _config.debug.showSkeleton) {
|
|
|
|
|
_skelImageWrapper.overlay(_canvasContainer.dom.binary, 360, imageRef(x, y));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* Extracts and describes those patches which seem to contain a barcode pattern
|
|
|
|
|
* @param {Array} moments
|
|
|
|
|
* @param {Object} patchPos,
|
|
|
|
@ -375,7 +379,7 @@ function skeletonize(x, y) {
|
|
|
|
|
* @param {Number} y
|
|
|
|
|
* @returns {Array} list of patches
|
|
|
|
|
*/
|
|
|
|
|
function describePatch(moments, patchPos, x, y) {
|
|
|
|
|
function describePatch(moments, patchPos, x, y) {
|
|
|
|
|
var k,
|
|
|
|
|
avg,
|
|
|
|
|
eligibleMoments = [],
|
|
|
|
@ -428,13 +432,13 @@ function describePatch(moments, patchPos, x, y) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return patchesFound;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
/**
|
|
|
|
|
* finds patches which are connected and share the same orientation
|
|
|
|
|
* @param {Object} patchesFound
|
|
|
|
|
*/
|
|
|
|
|
function rasterizeAngularSimilarity(patchesFound) {
|
|
|
|
|
function rasterizeAngularSimilarity(patchesFound) {
|
|
|
|
|
var label = 0,
|
|
|
|
|
threshold = 0.95,
|
|
|
|
|
currIdx = 0,
|
|
|
|
@ -523,17 +527,9 @@ function rasterizeAngularSimilarity(patchesFound) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return label;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
init: function(inputImageWrapper, config) {
|
|
|
|
|
_config = config;
|
|
|
|
|
_inputImageWrapper = inputImageWrapper;
|
|
|
|
|
|
|
|
|
|
initBuffers();
|
|
|
|
|
initCanvas();
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
locate: function() {
|
|
|
|
|
var patchesFound,
|
|
|
|
|
topLabels,
|
|
|
|
@ -564,9 +560,10 @@ export default {
|
|
|
|
|
|
|
|
|
|
boxes = findBoxes(topLabels, maxLabel);
|
|
|
|
|
return boxes;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
checkImageConstraints: function(inputStream, config) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
export function checkImageConstraints(inputStream, config) {
|
|
|
|
|
var patchSize,
|
|
|
|
|
width = inputStream.getWidth(),
|
|
|
|
|
height = inputStream.getHeight(),
|
|
|
|
@ -603,5 +600,4 @@ export default {
|
|
|
|
|
throw new Error("Image dimensions do not comply with the current settings: Width (" +
|
|
|
|
|
width + " )and height (" + height +
|
|
|
|
|
") must a multiple of " + patchSize.x);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|