Text erkennen liest den Zielrahmen in voller Auflösung, nicht das Vollbild

grabFrameRegion() statt grabFrame(): "Modul scannen" bekam bisher das ganze
Kamerabild, auf 1280 Pixel herunterskaliert - der Zielrahmen war dabei rein
kosmetisch, obwohl er dem Nutzer einen wirksamen Ausschnitt suggeriert. Jetzt
liest die Texterkennung genau den Rahmenausschnitt, in nativer Auflösung -
denselben, den auch die laufende Barcode-Suche längst benutzt. Die
Dateiauswahl (onPickFile) bleibt unverändert beim Vollbild, da sie keinen
Zielrahmen kennt.
This commit is contained in:
2026-07-29 15:18:48 +02:00
parent 3907204209
commit 54b1447f21
+22 -4
View File
@@ -1,6 +1,6 @@
// Vollstaendige Verdrahtung der App: Kamera, Barcode/OCR-Erkennung, Sitzung // Vollstaendige Verdrahtung der App: Kamera, Barcode/OCR-Erkennung, Sitzung
// und Oberflaeche. Ersetzt das fruehere Sichtpruefungs-Geruest vollstaendig. // und Oberflaeche. Ersetzt das fruehere Sichtpruefungs-Geruest vollstaendig.
import { startCamera, grabFrame, grabFrameRegion, imageDataFromFile } from './camera.js'; import { startCamera, grabFrameRegion, imageDataFromFile } from './camera.js';
import { decodeBarcodes } from './barcode.js'; import { decodeBarcodes } from './barcode.js';
import { runOcr, isOcrAvailable } from './ocr.js'; import { runOcr, isOcrAvailable } from './ocr.js';
import { recognize } from './pipeline.js'; import { recognize } from './pipeline.js';
@@ -50,7 +50,13 @@ let cameraUnavailableMessage = null;
let currentModeId = null; let currentModeId = null;
const view = renderScanView(app, { const view = renderScanView(app, {
onCapture: () => processCapture(() => grabFrame(view.video)), // "Modul scannen" ist nur in Funktion 3 ("Text erkennen") sichtbar (siehe
// applyMode()/setCaptureVisible) - der Zielrahmen suggeriert dem Nutzer dort
// einen Ausschnitt, den grabFrame() (Vollbild, herunterskaliert) bisher gar
// nicht einloeste. grabFrameRegion() liest genau den Rahmenausschnitt, in
// voller Aufloesung - derselbe Ausschnitt, den auch die Barcode-Dauersuche
// benutzt (siehe runSearchAttempt() weiter unten).
onCapture: () => processCapture(() => grabFrameRegion(view.video)),
onUndo: () => { onUndo: () => {
// Waehrend eine Erkennung laeuft, darf kein Eintrag zurueckgenommen // Waehrend eine Erkennung laeuft, darf kein Eintrag zurueckgenommen
// werden - sonst koennte die Rueckgaengig-Flaeche einen Eintrag treffen, // werden - sonst koennte die Rueckgaengig-Flaeche einen Eintrag treffen,
@@ -150,7 +156,7 @@ async function processCapture(getFrame) {
// selbst (pipeline.js) bleibt unveraendert und kennt keine Funktionen. // selbst (pipeline.js) bleibt unveraendert und kennt keine Funktionen.
const { decodeBarcodes: decode, runOcr: recognizeText } = const { decodeBarcodes: decode, runOcr: recognizeText } =
buildRecognitionAdapters(currentModeId, { decodeBarcodes, runOcr }); buildRecognitionAdapters(currentModeId, { decodeBarcodes, runOcr });
const { spec, source, confidence, codes } = await recognize( const { spec, source, confidence, codes, rawText } = await recognize(
frame, frame,
{ decodeBarcodes: decode, runOcr: recognizeText, isKnownCode }, { decodeBarcodes: decode, runOcr: recognizeText, isKnownCode },
); );
@@ -188,13 +194,25 @@ async function processCapture(getFrame) {
if (targetSession !== session) return; if (targetSession !== session) return;
const entry = commitAssignment(targetSession, spec, source, stackId, codes); const entry = commitAssignment(targetSession, spec, source, stackId, codes);
// entry.rawText ist rein additiv (siehe recognize() in pipeline.js) -
// session.js kennt das Feld nicht und bleibt deshalb unangetastet; es wird
// hier von aussen an den bereits gebuchten Eintrag angehaengt, genau wie
// die Stapelzuordnung selbst nie vom Rohtext abhaengt.
entry.rawText = rawText;
view.setLast(describeEntry(spec, entry.stackId)); view.setLast(describeEntry(spec, entry.stackId));
syncView(); syncView();
// Nach einer manuellen Entscheidung im Rot-Dialog gibt es nichts mehr // Nach einer manuellen Entscheidung im Rot-Dialog gibt es nichts mehr
// rueckzumelden - der Dialog selbst war die Rueckmeldung. // rueckzumelden - der Dialog selbst war die Rueckmeldung.
if (confidence !== 'red') { if (confidence !== 'red') {
await showResult(app, { stackId: entry.stackId, spec, confidence }); // Nur in Funktion 3 ("Text erkennen") ist der erkannte Text lang genug,
// dass er gelesen werden will - dort bleibt die Rueckmeldung deshalb
// stehen, bis der Nutzer sie wegtippt, statt sich nach kurzer Zeit von
// selbst auszublenden (siehe showResult()). In den beiden Barcode-
// Funktionen zaehlt Tempo, dort bleibt es beim automatischen Ausblenden.
await showResult(app, {
stackId: entry.stackId, spec, confidence, rawText, autoHide: currentModeId !== 'ocr',
});
} }
} catch (error) { } catch (error) {
failed = true; failed = true;