Behandle Mehrdeutigkeit auch bei unverwertbaren Barcodes
Mehrere Barcodes ohne bekanntes Nummernschema, die sich in der Teilenummer widersprechen, durften bisher nicht mehr Vorrang vor der per OCR gelesenen Teilenummer erhalten als ein einzelner Treffer - der erste gewann ungeprueft. Jetzt gilt derselbe Massstab wie bei verwertbaren Treffern: Vorrang nur bei Eindeutigkeit (ein Code, oder mehrere mit derselben - via canonical() verwechslungstolerant verglichenen - Teilenummer). Widersprechen sie sich, stuetzt sich das Ergebnis allein auf die Texterkennung. Zusaetzlich: ungueltige @param-Zeile fuer deps in recognize() korrigiert.
This commit is contained in:
+23
-9
@@ -1,4 +1,4 @@
|
||||
import { emptySpec, isUsable, specsCompatible } from './spec.js';
|
||||
import { canonical, emptySpec, isUsable, specsCompatible } from './spec.js';
|
||||
import { decodePartNumber } from './pn-decoder.js';
|
||||
import { extractFields } from './ocr-extract.js';
|
||||
|
||||
@@ -51,10 +51,10 @@ function allCompatible(specs) {
|
||||
|
||||
/**
|
||||
* Barcode zuerst, OCR nur als Rueckfallebene.
|
||||
* @param {object} deps.decodeBarcodes und deps.runOcr sind erforderlich.
|
||||
* deps.barcodeTimeoutMs und deps.ocrTimeoutMs sind optional und ueberschreiben
|
||||
* die eingebauten Obergrenzen - fuer Tests, die einen haengenden Adapter
|
||||
* simulieren, ohne tatsaechlich zu warten.
|
||||
* @param {object} deps Adapter- und Zeitgrenzen-Bundel: deps.decodeBarcodes und
|
||||
* deps.runOcr sind erforderlich. deps.barcodeTimeoutMs und deps.ocrTimeoutMs
|
||||
* sind optional und ueberschreiben die eingebauten Obergrenzen - fuer Tests,
|
||||
* die einen haengenden Adapter simulieren, ohne tatsaechlich zu warten.
|
||||
* @returns {Promise<{spec: object, source: 'barcode'|'ocr'|'none', confidence: 'green'|'yellow'|'red'}>}
|
||||
*/
|
||||
export async function recognize(frame, deps) {
|
||||
@@ -64,16 +64,30 @@ export async function recognize(frame, deps) {
|
||||
const decodedCodes = await safely(() => deps.decodeBarcodes(frame), [], barcodeTimeoutMs);
|
||||
const codes = Array.isArray(decodedCodes) ? decodedCodes : [];
|
||||
|
||||
let best = emptySpec();
|
||||
const usable = [];
|
||||
const unusable = [];
|
||||
for (const code of codes) {
|
||||
const decoded = decodePartNumber(code);
|
||||
if (isUsable(decoded)) {
|
||||
usable.push(decoded);
|
||||
continue;
|
||||
} else {
|
||||
unusable.push(decoded);
|
||||
}
|
||||
// Teilenummer merken, auch wenn das Schema unbekannt ist.
|
||||
if (best.partNumber === null) best = decoded;
|
||||
}
|
||||
|
||||
// Auch unter den nicht verwertbaren Barcodes (unbekanntes Nummernschema)
|
||||
// gilt: Vorrang vor der gelesenen Teilenummer nur, wenn er eindeutig ist.
|
||||
// Genau ein Code - oder mehrere mit uebereinstimmender Teilenummer - behaelt
|
||||
// seinen Vorrang samt abgeleiteter Felder. Widersprechen sich mehrere
|
||||
// untereinander, erhaelt keiner Vorrang; es wird nichts aus ihnen uebernommen.
|
||||
let best = emptySpec();
|
||||
const withPartNumber = unusable.filter((decoded) => decoded.partNumber !== null);
|
||||
if (withPartNumber.length > 0) {
|
||||
const first = withPartNumber[0];
|
||||
const allSameCode = withPartNumber.every(
|
||||
(decoded) => canonical(decoded.partNumber) === canonical(first.partNumber)
|
||||
);
|
||||
if (allSameCode) best = first;
|
||||
}
|
||||
|
||||
if (usable.length === 1) {
|
||||
|
||||
Reference in New Issue
Block a user