Files
ocr_scanner/test/count-objects-photo.test.js
T
TanerUsluandClaude Opus 5 75c479860f Zaehlung auf oertlichen Kontrast umgestellt (Otsu versagte am echten Foto)
Otsu (bisheriges Verfahren) meldete am echten Foto des Auftraggebers
(~20 Schrauben auf Leder, unter 1% Flaechenanteil) 76712 statt rund
zwanzig - Otsu taugt nur bei etwa gleich grossen Objekt-/
Untergrundflaechen. countObjects() vergleicht jetzt jeden Bildpunkt mit
einem oertlichen Hintergrund (Kastenfilter ueber Summenbild, Radius
max(Breite,Hoehe)/12), was Ausleuchtungsunterschiede abfaengt und am
echten Foto 18 statt 76712 liefert (Test in
test/count-objects-photo.test.js, ~30-49ms Laufzeit).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 16:21:13 +02:00

58 lines
2.3 KiB
JavaScript

// Prueffall am echten Foto des Auftraggebers (siehe
// .superpowers/sdd/counting-rework-report.md): Otsu allein scheiterte hier,
// weil die Schrauben unter einem Prozent der Bildflaeche belegen - Otsu
// rutscht in so einem Fall auf den hoechsten Helligkeitswert und erklaert nur
// die hellsten Punkte der Ledernarbung zum Objekt. Die fruehere Fassung
// meldete an genau diesem Bild 76712 statt der rund zwanzig tatsaechlich
// ausgelegten Schrauben. Dieser Test schuetzt vor einem Rueckfall in dieses
// Verhalten.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { countObjects } from '../src/count-objects.js';
import {
SCREWS_WIDTH,
SCREWS_HEIGHT,
SCREWS_GRAY_BASE64,
} from './fixtures/screws-photo.js';
/**
* Baut aus dem Base64-kodierten Graustufenraster ein ImageData-artiges
* Objekt: Graustufenwert auf R, G und B gelegt, Alpha 255 - wie eine echte
* Kameraaufnahme ohne Farbinformation.
*/
function grayscaleImage(width, height, base64) {
const gray = Buffer.from(base64, 'base64');
const data = new Uint8ClampedArray(width * height * 4);
for (let p = 0, i = 0; p < width * height; p += 1, i += 4) {
const value = gray[p];
data[i] = value;
data[i + 1] = value;
data[i + 2] = value;
data[i + 3] = 255;
}
return { width, height, data };
}
test('echtes Foto (~20 Festplattenschrauben auf Leder) ergibt eine Zahl zwischen 15 und 24', () => {
const imageData = grayscaleImage(SCREWS_WIDTH, SCREWS_HEIGHT, SCREWS_GRAY_BASE64);
const start = performance.now();
const result = countObjects(imageData);
const durationMs = performance.now() - start;
// Nur zur Beobachtung im Testlauf, keine Zusicherung ueber die Konsole -
// die Laufzeit selbst wird unten geprueft.
console.log(`countObjects(screws-photo) dauerte ${durationMs.toFixed(2)} ms`);
assert.ok(
result.count >= 15 && result.count <= 24,
`erwartet 15..24, erhalten ${result.count} (fruehere Fassung meldete 76712)`,
);
// Soll mehrmals je Sekunde laufen koennen (laufende Anzeige waehrend die
// Kamera laeuft) - grosszuegige Grenze, die auf langsamerer Hardware nicht
// faelschlich anschlaegt, aber ein grundlegend zu langsames Verfahren
// (z. B. eine versehentlich quadratische Rechnung) auffangen wuerde.
assert.ok(durationMs < 500, `erwartet unter 500 ms, gemessen ${durationMs.toFixed(2)} ms`);
});