nfv
Version:
[Updated to use ndv package instead dv] FormVision is a node.js library for extracting data from scanned forms
55 lines (51 loc) • 2 kB
text/coffeescript
{unpack, validate} = require './schema'
{distanceVector, length, center} = require './math'
barcodeToValue = (barcode) ->
type: barcode.type
data: barcode.data
buffer: barcode.buffer
# Match barcode data to form schema.
module.exports.matchBarcodes = (formData, formSchema, barcodes, schemaToPage) ->
barcodeFields = formSchema.fields.filter (field) -> field.type is 'barcode'
# Map barcodes and fields to matches.
matchMap = {}
for barcode in barcodes
value = barcodeToValue barcode
validFields = barcodeFields.filter (field) -> validate field, value, false
for field in validFields
# 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
continue if distance > radius * field.searchRadius
matchMap[field.path] ?= []
matchMap[field.path].push
barcode: barcode
paths: validFields.map (field) -> field.path
# Reduce matches to fields.
for field in barcodeFields
if matchMap[field.path]?
matches = matchMap[field.path]
# Many barcodes to one field resolution.
if matches.length > 1 and field.fieldSelector?
values = matches.map (match) -> barcodeToValue match.barcode
choice = field.fieldSelector values
confidence = 100
if choice not of 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 (path) -> path isnt field.path
else
fieldData = unpack formData, field.path
fieldData.confidence = 0
fieldData.box = schemaToPage field.box
fieldData.conflicts = []
return