diff --git a/public/js/ar/detect.js b/public/js/ar/detect.js index 3ab7bd5..59a75de 100644 --- a/public/js/ar/detect.js +++ b/public/js/ar/detect.js @@ -14,9 +14,25 @@ export function createDetector() { */ export function detectMarkers(detector, imageData, knownIds) { const raw = detector.detect(imageData).filter(m => quadArea(m.corners) > 100); - const usable = (knownIds && knownIds.size) ? raw.filter(m => knownIds.has(m.id)) : []; + + /* Deduplicate by id. Two quads in one frame can decode to the same id — a + * misread of a different crest under blur or glare. That is poison for the + * board solve: both quads are handed the SAME world corners, so solvePnP gets + * two contradictory constraints for one point set and the pose collapses + * (seen on device as reproj jumping to 5px+). Keep the largest quad, which is + * the closest and best-resolved reading. */ + const best = new Map(); + for (const m of raw) { + const area = quadArea(m.corners); + const prev = best.get(m.id); + if (!prev || area > prev.area) best.set(m.id, { m, area }); + } + const uniq = [...best.values()].map(e => e.m); + + const usable = (knownIds && knownIds.size) ? uniq.filter(m => knownIds.has(m.id)) : []; usable.rawCount = raw.length; usable.rawIds = raw.map(m => m.id); + usable.dupes = raw.length - uniq.length; return usable; }