mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-12 21:21:42 +08:00
Preparing pdf417 decoding
This commit is contained in:
@@ -19,14 +19,12 @@
|
||||
/* line 1, ../sass/_viewport.scss */
|
||||
#interactive.viewport {
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
}
|
||||
|
||||
/* line 6, ../sass/_viewport.scss */
|
||||
#interactive.viewport canvas, video {
|
||||
float: left;
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
}
|
||||
/* line 10, ../sass/_viewport.scss */
|
||||
#interactive.viewport canvas.drawingBuffer, video.drawingBuffer {
|
||||
|
||||
@@ -88,16 +88,17 @@ $(function() {
|
||||
},
|
||||
state: {
|
||||
inputStream: {
|
||||
size: 640,
|
||||
size: 800,
|
||||
singleChannel: false
|
||||
},
|
||||
locator: {
|
||||
patchSize: "large",
|
||||
halfSample: false
|
||||
halfSample: true
|
||||
},
|
||||
decoder: {
|
||||
readers: ["code_128_reader"]
|
||||
readers: ["pdf_417_reader"]
|
||||
},
|
||||
debug: true,
|
||||
locate: true,
|
||||
src: null
|
||||
}
|
||||
@@ -131,7 +132,7 @@ $(function() {
|
||||
drawingCanvas = Quagga.canvas.dom.overlay,
|
||||
area;
|
||||
|
||||
if (result) {
|
||||
if (false) {
|
||||
if (result.boxes) {
|
||||
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||
result.boxes.filter(function (box) {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
|
||||
export function getCenterLineFromBox(box) {
|
||||
return [{
|
||||
x: (box[1][0] - box[0][0]) / 2 + box[0][0],
|
||||
y: (box[1][1] - box[0][1]) / 2 + box[0][1]
|
||||
}, {
|
||||
x: (box[3][0] - box[2][0]) / 2 + box[2][0],
|
||||
y: (box[3][1] - box[2][1]) / 2 + box[2][1]
|
||||
}];
|
||||
}
|
||||
|
||||
export function getLineLength(line) {
|
||||
return Math.sqrt(
|
||||
Math.pow(Math.abs(line[1].y - line[0].y), 2) +
|
||||
Math.pow(Math.abs(line[1].x - line[0].x), 2));
|
||||
}
|
||||
|
||||
export function getLineAngle(line) {
|
||||
return Math.atan2(line[1].y - line[0].y, line[1].x - line[0].x);
|
||||
}
|
||||
|
||||
function extendLine(line, angle, ext) {
|
||||
const extension = {
|
||||
y: ext * Math.sin(angle),
|
||||
x: ext * Math.cos(angle)
|
||||
};
|
||||
|
||||
line[0].y -= extension.y;
|
||||
line[0].x -= extension.x;
|
||||
line[1].y += extension.y;
|
||||
line[1].x += extension.x;
|
||||
return line;
|
||||
}
|
||||
|
||||
export function getExtendedLine(inputImageWrapper, line, angle, ext) {
|
||||
line = extendLine(line, angle, ext);
|
||||
while (ext > 1 && (!inputImageWrapper.inImageWithBorder(line[0], 0)
|
||||
|| !inputImageWrapper.inImageWithBorder(line[1], 0))) {
|
||||
ext -= Math.ceil(ext / 2);
|
||||
line = extendLine(line, angle, -ext);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
@@ -15,9 +15,24 @@ export default {
|
||||
for (var j = 1; j < path.length; j++) {
|
||||
ctx.lineTo(path[j][def.x], path[j][def.y]);
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
},
|
||||
drawVertex: function(vertex, def, ctx) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(vertex[def.x]-2, vertex[def.y]-2);
|
||||
ctx.lineTo(vertex[def.x]+2, vertex[def.y]+2);
|
||||
ctx.moveTo(vertex[def.x]-2, vertex[def.y]+2);
|
||||
ctx.lineTo(vertex[def.x]+2, vertex[def.y]-2);
|
||||
ctx.stroke();
|
||||
},
|
||||
drawVertices: function(vertices, def, ctx, style) {
|
||||
ctx.strokeStyle = style.color;
|
||||
ctx.fillStyle = style.color;
|
||||
ctx.lineWidth = style.lineWidth;
|
||||
vertices.forEach((vertex) => {
|
||||
this.drawVertex(vertex, def, ctx);
|
||||
});
|
||||
},
|
||||
drawImage: function(imageData, size, ctx) {
|
||||
var canvasData = ctx.getImageData(0, 0, size.x, size.y),
|
||||
data = canvasData.data,
|
||||
|
||||
@@ -9,6 +9,13 @@ import UPCReader from '../reader/upc_reader';
|
||||
import EAN8Reader from '../reader/ean_8_reader';
|
||||
import UPCEReader from '../reader/upc_e_reader';
|
||||
import I2of5Reader from '../reader/i2of5_reader';
|
||||
import Pdf417Reader from '../reader/pdf_417_reader';
|
||||
import {
|
||||
getCenterLineFromBox as getLine,
|
||||
getLineLength,
|
||||
getLineAngle,
|
||||
getExtendedLine
|
||||
} from '../common/geometric';
|
||||
|
||||
const READERS = {
|
||||
code_128_reader: Code128Reader,
|
||||
@@ -19,7 +26,8 @@ const READERS = {
|
||||
codabar_reader: CodabarReader,
|
||||
upc_reader: UPCReader,
|
||||
upc_e_reader: UPCEReader,
|
||||
i2of5_reader: I2of5Reader
|
||||
i2of5_reader: I2of5Reader,
|
||||
pdf_417_reader: Pdf417Reader
|
||||
};
|
||||
export default {
|
||||
create: function(config, inputImageWrapper) {
|
||||
@@ -115,44 +123,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* extend the line on both ends
|
||||
* @param {Array} line
|
||||
* @param {Number} angle
|
||||
*/
|
||||
function getExtendedLine(line, angle, ext) {
|
||||
function extendLine(amount) {
|
||||
var extension = {
|
||||
y: amount * Math.sin(angle),
|
||||
x: amount * Math.cos(angle)
|
||||
};
|
||||
|
||||
line[0].y -= extension.y;
|
||||
line[0].x -= extension.x;
|
||||
line[1].y += extension.y;
|
||||
line[1].x += extension.x;
|
||||
}
|
||||
|
||||
// check if inside image
|
||||
extendLine(ext);
|
||||
while (ext > 1 && (!inputImageWrapper.inImageWithBorder(line[0], 0)
|
||||
|| !inputImageWrapper.inImageWithBorder(line[1], 0))) {
|
||||
ext -= Math.ceil(ext / 2);
|
||||
extendLine(-ext);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
function getLine(box) {
|
||||
return [{
|
||||
x: (box[1][0] - box[0][0]) / 2 + box[0][0],
|
||||
y: (box[1][1] - box[0][1]) / 2 + box[0][1]
|
||||
}, {
|
||||
x: (box[3][0] - box[2][0]) / 2 + box[2][0],
|
||||
y: (box[3][1] - box[2][1]) / 2 + box[2][1]
|
||||
}];
|
||||
}
|
||||
|
||||
function tryDecode(line) {
|
||||
var result = null,
|
||||
i,
|
||||
@@ -215,12 +185,6 @@ export default {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getLineLength(line) {
|
||||
return Math.sqrt(
|
||||
Math.pow(Math.abs(line[1].y - line[0].y), 2) +
|
||||
Math.pow(Math.abs(line[1].x - line[0].x), 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* With the help of the configured readers (Code128 or EAN) this function tries to detect a
|
||||
* valid barcode pattern within the given area.
|
||||
@@ -240,10 +204,17 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
if (_barcodeReaders.some((reader) => (reader.FORMAT === 'pdf147'))) {
|
||||
const reader = _barcodeReaders
|
||||
.filter((reader) => (reader.FORMAT === 'pdf147'))[0];
|
||||
reader.decode(inputImageWrapper, box, ctx);
|
||||
return null;
|
||||
}
|
||||
|
||||
line = getLine(box);
|
||||
lineLength = getLineLength(line);
|
||||
lineAngle = Math.atan2(line[1].y - line[0].y, line[1].x - line[0].x);
|
||||
line = getExtendedLine(line, lineAngle, Math.floor(lineLength * 0.1));
|
||||
lineAngle = getLineAngle(line);
|
||||
line = getExtendedLine(inputImageWrapper, line, lineAngle, Math.floor(lineLength * 0.1));
|
||||
if (line === null){
|
||||
return null;
|
||||
}
|
||||
@@ -279,6 +250,7 @@ export default {
|
||||
barcodes = [],
|
||||
multiple = config.multiple;
|
||||
|
||||
console.log(boxes);
|
||||
for ( i = 0; i < boxes.length; i++) {
|
||||
const box = boxes[i];
|
||||
result = decodeFromBoundingBox(box) || {};
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import {
|
||||
getCenterLineFromBox as getLine,
|
||||
getLineLength,
|
||||
getLineAngle,
|
||||
getExtendedLine
|
||||
} from '../common/geometric';
|
||||
import ImageDebug from '../common/image_debug';
|
||||
import Bresenham from '../decoder/bresenham';
|
||||
import {findPattern} from '../reader/common';
|
||||
|
||||
const vec2 = {
|
||||
clone: require('gl-vec2/clone'),
|
||||
dot: require('gl-vec2/dot')
|
||||
}
|
||||
|
||||
const START_PATTERN = [8, 1, 1, 1, 1, 1, 1, 3],
|
||||
STOP_PATTERN = [7, 1, 1, 3, 1, 1, 1, 2, 1],
|
||||
MODULO = START_PATTERN.reduce((sum, i) => (sum + i),0);
|
||||
|
||||
export default function detect(inputImageWrapper, box, ctx) {
|
||||
let line = getLine(box),
|
||||
lineLength = getLineLength(line),
|
||||
lineAngle = getLineAngle(line),
|
||||
extendedLine = getExtendedLine(inputImageWrapper, line, lineAngle, Math.floor(lineLength * 0.15)),
|
||||
barcodeLine = Bresenham.getBarcodeLine(inputImageWrapper, extendedLine[0], extendedLine[1]);
|
||||
|
||||
if (ENV.development) {
|
||||
if (ctx) {
|
||||
ImageDebug.drawPath(extendedLine, {x: 'x', y: 'y'}, ctx, {color: 'red', lineWidth: 1});
|
||||
}
|
||||
}
|
||||
|
||||
Bresenham.toBinaryLine(barcodeLine);
|
||||
|
||||
const match = findPattern(barcodeLine.line, START_PATTERN, {modulo: MODULO});
|
||||
console.log(match);
|
||||
|
||||
return [
|
||||
vec2.clone([199, 84]),
|
||||
vec2.clone([210, 303]),
|
||||
vec2.clone([634, 88]),
|
||||
vec2.clone([660, 271]),
|
||||
vec2.clone([295, 83]),
|
||||
vec2.clone([310, 295]),
|
||||
vec2.clone([554, 83]),
|
||||
vec2.clone([580, 277])
|
||||
]
|
||||
};
|
||||
@@ -0,0 +1,126 @@
|
||||
export function nextSet(line, offset) {
|
||||
var i;
|
||||
|
||||
offset = offset || 0;
|
||||
for (i = offset; i < line.length; i++) {
|
||||
if (line[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return line.length;
|
||||
};
|
||||
|
||||
export function normalize(counter, modulo) {
|
||||
var i,
|
||||
sum = 0,
|
||||
ratio,
|
||||
numOnes = 0,
|
||||
normalized = [],
|
||||
norm = 0;
|
||||
|
||||
for (i = 0; i < counter.length; i++) {
|
||||
if (counter[i] === 1) {
|
||||
numOnes++;
|
||||
} else {
|
||||
sum += counter[i];
|
||||
}
|
||||
}
|
||||
ratio = sum / (modulo - numOnes);
|
||||
if (ratio > 1.0) {
|
||||
for (i = 0; i < counter.length; i++) {
|
||||
norm = counter[i] === 1 ? counter[i] : counter[i] / ratio;
|
||||
normalized.push(norm);
|
||||
}
|
||||
} else {
|
||||
ratio = (sum + numOnes) / modulo;
|
||||
for (i = 0; i < counter.length; i++) {
|
||||
norm = counter[i] / ratio;
|
||||
normalized.push(norm);
|
||||
}
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function matchPattern(counter, code, modulo, maxSingleError=1) {
|
||||
var i,
|
||||
error = 0,
|
||||
singleError = 0;
|
||||
|
||||
for (i = 0; i < counter.length; i++) {
|
||||
singleError = Math.abs(code[i] - counter[i]);
|
||||
if (singleError > maxSingleError) {
|
||||
return Number.MAX_VALUE;
|
||||
}
|
||||
error += singleError;
|
||||
}
|
||||
return error / modulo;
|
||||
}
|
||||
|
||||
export function findPattern(row, pattern, {
|
||||
offset,
|
||||
isWhite=false,
|
||||
tryHarder=true,
|
||||
epsilon=0.5,
|
||||
maxSingleError=0.5,
|
||||
modulo}) {
|
||||
var counter = [],
|
||||
i,
|
||||
counterPos = 0,
|
||||
bestMatch = {
|
||||
error: Number.MAX_VALUE,
|
||||
code: -1,
|
||||
start: 0,
|
||||
end: 0
|
||||
},
|
||||
error,
|
||||
j,
|
||||
sum,
|
||||
normalized;
|
||||
|
||||
if (!offset) {
|
||||
offset = nextSet(row);
|
||||
}
|
||||
|
||||
for ( i = 0; i < pattern.length; i++) {
|
||||
counter[i] = 0;
|
||||
}
|
||||
|
||||
for ( i = offset; i < row.length; i++) {
|
||||
if (row[i] ^ isWhite) {
|
||||
counter[counterPos]++;
|
||||
} else {
|
||||
if (counterPos === counter.length - 1) {
|
||||
sum = 0;
|
||||
for ( j = 0; j < counter.length; j++) {
|
||||
sum += counter[j];
|
||||
}
|
||||
normalized = normalize(counter, modulo);
|
||||
if (normalized) {
|
||||
error = matchPattern(normalized, pattern, modulo, maxSingleError);
|
||||
|
||||
if (error < epsilon) {
|
||||
bestMatch.error = error;
|
||||
bestMatch.start = i - sum;
|
||||
bestMatch.end = i;
|
||||
return bestMatch;
|
||||
}
|
||||
}
|
||||
if (tryHarder) {
|
||||
for ( j = 0; j < counter.length - 2; j++) {
|
||||
counter[j] = counter[j + 2];
|
||||
}
|
||||
counter[counter.length - 2] = 0;
|
||||
counter[counter.length - 1] = 0;
|
||||
counterPos--;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
counterPos++;
|
||||
}
|
||||
counter[counterPos] = 1;
|
||||
isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import BarcodeReader from './barcode_reader';
|
||||
import detect from '../detector/pdf_147_detector';
|
||||
import ImageDebug from '../common/image_debug';
|
||||
|
||||
function Pdf147Reader() {
|
||||
BarcodeReader.call(this);
|
||||
}
|
||||
|
||||
const properties = {
|
||||
SINGLE_CODE_ERROR: {value: 1},
|
||||
AVG_CODE_ERROR: {value: 0.5},
|
||||
FORMAT: {value: "pdf147", writeable: false}
|
||||
};
|
||||
|
||||
Pdf147Reader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||
Pdf147Reader.prototype.constructor = Pdf147Reader;
|
||||
|
||||
Pdf147Reader.prototype.decode = function(inputImageWrapper, box, ctx) {
|
||||
console.log("Pdf147Reader...");
|
||||
const detectionInfo = detect(inputImageWrapper, box, ctx);
|
||||
console.log(detectionInfo);
|
||||
if (ENV.development) {
|
||||
if (ctx) {
|
||||
ImageDebug.drawVertices(detectionInfo, {x: 0, y: 1}, ctx, {color: "red", lineWidth: 1});
|
||||
}
|
||||
}
|
||||
console.log("Pdf147Reader... END")
|
||||
};
|
||||
|
||||
export default Pdf147Reader;
|
||||
Reference in New Issue
Block a user