Zählen: Aufnahme statt Dauerbetrieb
Die Zaehlanzeige sprang beim Nutzer im Dauerbetrieb wild zwischen etwa 3 und 60, obwohl dasselbe Verfahren an einem Standfoto stabil 18 lieferte - eine Schaetzung wird durch staendiges Neuanzeigen nicht praeziser, nur unruhig. "Zählen" laeuft jetzt wie "Text erkennen" auf Knopfdruck: eine Aufnahme nimmt binnen rund einer Sekunde fuenf Bilder aus dem Zielrahmen auf, zaehlt jedes einzeln (count-objects.js unveraendert) und zeigt deren Median (neues Modul count-capture.js). Das Ergebnis bleibt stehen, bis erneut angetippt wird; die Diagnosezeile zeigt zusaetzlich die fuenf Einzelmessungen. Der gleitende Median ueber neun Durchlaeufe der Dauerzaehlung (count-history.js) entfaellt, da die Aufnahme dieselbe Robustheit bereits selbst leistet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
// Reine Rechenlogik der Zaehl-Aufnahme (Funktion "Zählen", siehe main.js):
|
||||
// aus den (bis zu fuenf) Einzelmessungen einer Aufnahme wird deren Median
|
||||
// gebildet. Siehe count-capture.js fuer die Begruendung (robust gegen einen
|
||||
// einzelnen Ausreisser, ohne wie eine fortlaufende Glaettung traege zu sein).
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { combineCaptureCounts } from '../src/count-capture.js';
|
||||
|
||||
test('fuenf gleiche Messungen liefern diese Zahl', () => {
|
||||
assert.equal(combineCaptureCounts([18, 18, 18, 18, 18]), 18);
|
||||
});
|
||||
|
||||
test('fuenf verschiedene Messungen liefern deren Median (ungerade Anzahl)', () => {
|
||||
assert.equal(combineCaptureCounts([17, 19, 18, 20, 18]), 18);
|
||||
});
|
||||
|
||||
test('ein einzelner grober Ausreisser unter fuenf Messungen schlaegt nicht durch', () => {
|
||||
// Vier stabile Messungen um 18 herum, eine grob daneben (z. B.
|
||||
// Bewegungsunschaerfe oder Autofokus mitten in der Aufnahme) - der Median
|
||||
// bleibt bei 18, ein Mittelwert waere durch den Ausreisser spuerbar verzerrt.
|
||||
assert.equal(combineCaptureCounts([18, 18, 3, 18, 60]), 18);
|
||||
});
|
||||
|
||||
test('weniger als fuenf Messungen (eine Kameraaufnahme scheiterte) liefern trotzdem ein Ergebnis', () => {
|
||||
// Gerade Anzahl (vier statt fuenf) - Median ist der Mittelwert der beiden
|
||||
// mittleren Werte.
|
||||
const result = combineCaptureCounts([17, 18, 18, 19]);
|
||||
assert.equal(result, 18);
|
||||
});
|
||||
|
||||
test('nur eine einzige verwertbare Messung ist ihr eigener Median', () => {
|
||||
assert.equal(combineCaptureCounts([21]), 21);
|
||||
});
|
||||
|
||||
test('eine leere Messreihe wirft, statt stillschweigend ein sinnloses Ergebnis (NaN) zu liefern', () => {
|
||||
assert.throws(() => combineCaptureCounts([]));
|
||||
});
|
||||
|
||||
test('combineCaptureCounts veraendert die uebergebene Liste nicht (reine Funktion)', () => {
|
||||
const counts = [5, 1, 3];
|
||||
const untouched = [...counts];
|
||||
combineCaptureCounts(counts);
|
||||
assert.deepEqual(counts, untouched);
|
||||
});
|
||||
@@ -1,71 +0,0 @@
|
||||
// Gleitender Verlauf der letzten Zaehlmessungen (Funktion "Zählen") - die
|
||||
// grosse Anzeige zeigt zusaetzlich zur rohen Messung deren Median ueber die
|
||||
// letzten neun Durchlaeufe, damit ein einzelner Ausreisser (Bewegungs-
|
||||
// unschaerfe, nachregelnder Autofokus) nicht sofort die Anzeige springen
|
||||
// laesst. Reines, browserfreies Modul wie count-objects.js - hier ohne
|
||||
// jeden Bezug zu Bilddaten, nur die Zahlenreihe selbst.
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { createCountHistory, pushCount, HISTORY_WINDOW } from '../src/count-history.js';
|
||||
|
||||
test('leerer Verlauf: die erste Messung ist zugleich ihr eigener Median', () => {
|
||||
const history = createCountHistory();
|
||||
const result = pushCount(history, 18);
|
||||
assert.deepEqual(result.history, [18]);
|
||||
assert.equal(result.median, 18);
|
||||
});
|
||||
|
||||
test('ein einzelner Ausreisser wird vom Median unterdrueckt', () => {
|
||||
let history = createCountHistory();
|
||||
// Acht stabile Messungen ...
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
({ history } = pushCount(history, 18));
|
||||
}
|
||||
// ... und ein einzelner Ausreisser (z. B. Bewegungsunschaerfe oder
|
||||
// nachregelnder Autofokus, siehe Modul-Doku).
|
||||
const result = pushCount(history, 60);
|
||||
assert.equal(
|
||||
result.median,
|
||||
18,
|
||||
'ein einzelner Ausreisser darf die geglaettete Anzeige nicht verschieben',
|
||||
);
|
||||
});
|
||||
|
||||
test('nach genuegend gleichbleibenden neuen Messungen folgt der Median (nicht traege)', () => {
|
||||
// Der Median glaettet nur einzelne Ausreisser, nicht eine echte,
|
||||
// anhaltende Aenderung (z. B. weil der Nutzer tatsaechlich Teile
|
||||
// weggenommen hat) - sonst waere die Anzeige "beruhigt", aber nicht mehr
|
||||
// ehrlich.
|
||||
let history = createCountHistory();
|
||||
for (let i = 0; i < 8; i += 1) {
|
||||
({ history } = pushCount(history, 18));
|
||||
}
|
||||
let result;
|
||||
for (let i = 0; i < HISTORY_WINDOW; i += 1) {
|
||||
result = pushCount(history, 5);
|
||||
history = result.history;
|
||||
}
|
||||
assert.equal(
|
||||
result.median,
|
||||
5,
|
||||
'nach HISTORY_WINDOW gleichen neuen Messungen ist der alte Wert vollstaendig aus dem Fenster verdraengt',
|
||||
);
|
||||
});
|
||||
|
||||
test('das Fenster behaelt hoechstens HISTORY_WINDOW Messungen - aeltere fallen heraus', () => {
|
||||
let history = createCountHistory();
|
||||
for (let i = 1; i <= HISTORY_WINDOW + 3; i += 1) {
|
||||
({ history } = pushCount(history, i));
|
||||
}
|
||||
assert.equal(history.length, HISTORY_WINDOW);
|
||||
// Die drei aeltesten (1, 2, 3) sind bereits herausgefallen.
|
||||
assert.deepEqual(history, [4, 5, 6, 7, 8, 9, 10, 11, 12]);
|
||||
});
|
||||
|
||||
test('pushCount veraendert den uebergebenen Verlauf nicht (reine Funktion)', () => {
|
||||
const history = createCountHistory();
|
||||
const before = pushCount(history, 3).history;
|
||||
const untouched = [...history];
|
||||
pushCount(before, 4);
|
||||
assert.deepEqual(history, untouched, 'der urspruengliche Verlauf bleibt unangetastet');
|
||||
});
|
||||
@@ -43,13 +43,12 @@ test('Funktion 3 (Text erkennen): keine Codearten, keine laufende Suche, Texterk
|
||||
assert.equal(mode.useOcr, true);
|
||||
});
|
||||
|
||||
test('Funktion 4 (Zählen): keine Codearten, keine laufende Codesuche, keine Texterkennung, dafuer laufende Zaehlung', () => {
|
||||
test('Funktion 4 (Zählen): keine Codearten, keine laufende Codesuche, keine Texterkennung - auf Knopfdruck wie Funktion 3', () => {
|
||||
const mode = getScanMode('count');
|
||||
assert.equal(mode.label, 'Zählen');
|
||||
assert.deepEqual(mode.barcodeFormats, []);
|
||||
assert.equal(mode.continuousSearch, false);
|
||||
assert.equal(mode.useOcr, false);
|
||||
assert.equal(mode.continuousCount, true);
|
||||
});
|
||||
|
||||
test('unbekannte Kennung wirft statt undefined zurueckzugeben', () => {
|
||||
|
||||
Reference in New Issue
Block a user