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>
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
// 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`);
|
||||
});
|
||||
Vendored
+10
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user