fv
Version:
FormVision is a node.js library for extracting data from scanned forms
87 lines (82 loc) • 3 kB
JavaScript
// Generated by CoffeeScript 2.3.1
var barcodeToValue, center, distanceVector, length, unpack, validate;
({unpack, validate} = require('./schema'));
({distanceVector, length, center} = require('./math'));
barcodeToValue = function(barcode) {
return {
type: barcode.type,
data: barcode.data,
buffer: barcode.buffer
};
};
// Match barcode data to form schema.
module.exports.matchBarcodes = function(formData, formSchema, barcodes, schemaToPage) {
var barcode, barcodeFields, choice, confidence, distance, field, fieldData, i, j, k, len, len1, len2, matchMap, matches, name, projection, radius, validFields, value, values;
barcodeFields = formSchema.fields.filter(function(field) {
return field.type === 'barcode';
});
// Map barcodes and fields to matches.
matchMap = {};
for (i = 0, len = barcodes.length; i < len; i++) {
barcode = barcodes[i];
value = barcodeToValue(barcode);
validFields = barcodeFields.filter(function(field) {
return validate(field, value, false);
});
for (j = 0, len1 = validFields.length; j < len1; j++) {
field = validFields[j];
// If searchRadius is set, additionally filter matches by distance
if (field.searchRadius > 0) {
projection = schemaToPage(field.box);
distance = length(distanceVector(center(projection), center(barcode.box)));
radius = Math.max(projection.width, projection.height) / 2;
if (distance > radius * field.searchRadius) {
continue;
}
}
if (matchMap[name = field.path] == null) {
matchMap[name] = [];
}
matchMap[field.path].push({
barcode: barcode,
paths: validFields.map(function(field) {
return field.path;
})
});
}
}
// Reduce matches to fields.
for (k = 0, len2 = barcodeFields.length; k < len2; k++) {
field = barcodeFields[k];
if (matchMap[field.path] != null) {
matches = matchMap[field.path];
// Many barcodes to one field resolution.
if (matches.length > 1 && (field.fieldSelector != null)) {
values = matches.map(function(match) {
return barcodeToValue(match.barcode);
});
choice = field.fieldSelector(values);
confidence = 100;
if (!(choice in values)) {
throw new Error('Returned choice index out of bounds');
}
} else {
choice = 0;
confidence = 100 / matches.length;
}
// Assign to field.
fieldData = unpack(formData, field.path);
fieldData.value = barcodeToValue(matches[choice].barcode);
fieldData.confidence = confidence;
fieldData.box = matches[choice].barcode.box;
fieldData.conflicts = matches[choice].paths.filter(function(path) {
return path !== field.path;
});
} else {
fieldData = unpack(formData, field.path);
fieldData.confidence = 0;
fieldData.box = schemaToPage(field.box);
fieldData.conflicts = [];
}
}
};