From db37d3c179cc4c1e7564598eaa9df2b702fffa65 Mon Sep 17 00:00:00 2001 From: Boki Date: Fri, 13 Feb 2026 15:07:03 -0500 Subject: [PATCH] much better --- src/Poe2Trade.Navigation/WorldMap.cs | 55 +++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/src/Poe2Trade.Navigation/WorldMap.cs b/src/Poe2Trade.Navigation/WorldMap.cs index f8d4252..d130aef 100644 --- a/src/Poe2Trade.Navigation/WorldMap.cs +++ b/src/Poe2Trade.Navigation/WorldMap.cs @@ -34,18 +34,15 @@ public class WorldMap : IDisposable var sw = Stopwatch.StartNew(); _frameCount++; - // Noise gate: skip frames with too many wall pixels (waypoint glow, effects) - // But NOT during warmup or re-bootstrap — we need to stitch something to get started - var wallPixels = Cv2.CountNonZero(wallMask); - var totalPixels = wallMask.Width * wallMask.Height; - var density = (double)wallPixels / totalPixels; - var isNoisy = density > _config.WallMaxDensity; var needsBootstrap = _frameCount <= _config.WarmupFrames || _consecutiveMatchFails >= 30; - if (isNoisy && !needsBootstrap) + // Block-based noise filter: zero out 50×50 blocks with >25% wall density + // Removes localized glow (waypoints, effects) while preserving real walls + var cleanFraction = FilterNoisyBlocks(wallMask, classifiedMat); + if (cleanFraction < 0.25 && !needsBootstrap) { - Log.Information("Noise gate: {Density:P1} wall density ({Pixels} px), skipping ({Ms:F1}ms)", - density, wallPixels, sw.Elapsed.TotalMilliseconds); + Log.Information("Noise filter: {Clean:P0} clean, skipping ({Ms:F1}ms)", + cleanFraction, sw.Elapsed.TotalMilliseconds); return _position; } @@ -260,6 +257,46 @@ public class WorldMap : IDisposable } } + /// + /// Zero out 50×50 blocks where wall density exceeds 25%. + /// Modifies wallMask and classifiedMat in-place. + /// Returns fraction of blocks that are clean (0.0–1.0). + /// + private static double FilterNoisyBlocks(Mat wallMask, Mat classifiedMat, + int blockSize = 50, double blockMaxDensity = 0.25) + { + var rows = wallMask.Rows; + var cols = wallMask.Cols; + var totalBlocks = 0; + var cleanBlocks = 0; + + for (var by = 0; by < rows; by += blockSize) + for (var bx = 0; bx < cols; bx += blockSize) + { + var bw = Math.Min(blockSize, cols - bx); + var bh = Math.Min(blockSize, rows - by); + totalBlocks++; + + var blockRect = new Rect(bx, by, bw, bh); + using var blockRoi = new Mat(wallMask, blockRect); + var wallCount = Cv2.CountNonZero(blockRoi); + + if ((double)wallCount / (bw * bh) > blockMaxDensity) + { + // Zero out this noisy block in both mats + blockRoi.SetTo(Scalar.Black); + using var classBlock = new Mat(classifiedMat, blockRect); + classBlock.SetTo(Scalar.Black); + } + else + { + cleanBlocks++; + } + } + + return totalBlocks > 0 ? (double)cleanBlocks / totalBlocks : 1.0; + } + public (double dirX, double dirY)? FindNearestUnexplored(MapPosition pos, int searchRadius = 200) { var cx = (int)Math.Round(pos.X);