work on minimap

This commit is contained in:
Boki 2026-02-13 12:30:13 -05:00
parent a152a5cead
commit 6bc3fb6972
3 changed files with 39 additions and 66 deletions

View file

@ -70,15 +70,11 @@ public class MinimapCapture : IDisposable
// --- 3. Wall mask: bright OR saturated → structure lines ---
using var wallMask = BuildWallMask(satChan, valueChan, playerMask);
// --- 4. Explored mask: brightness above fog-of-war, minus walls/player ---
using var exploredMask = BuildExploredMask(valueChan, wallMask, playerMask);
// --- 5. Build raw classified mat ---
// --- 4. Build classified mat (walls only — explored is tracked by WorldMap) ---
var classified = new Mat(_config.CaptureSize, _config.CaptureSize, MatType.CV_8UC1, Scalar.Black);
classified.SetTo(new Scalar((byte)MapCell.Explored), exploredMask);
classified.SetTo(new Scalar((byte)MapCell.Wall), wallMask);
// --- 6. Temporal smoothing: majority vote ---
// --- 5. Temporal smoothing: majority vote on walls ---
var smoothed = TemporalSmooth(classified); // classified goes into ring buffer
// --- 7. Gray for phase correlation (player zeroed — it stays centered, walls shift with map) ---
@ -118,23 +114,6 @@ public class MinimapCapture : IDisposable
return wallMask;
}
private Mat BuildExploredMask(Mat valueChan, Mat wallMask, Mat playerMask)
{
// Explored = any pixel above fog-of-war darkness, minus walls and player
var exploredMask = new Mat();
Cv2.Threshold(valueChan, exploredMask, _config.FloorMinValue, 255, ThresholdTypes.Binary);
using var notWall = new Mat();
Cv2.BitwiseNot(wallMask, notWall);
Cv2.BitwiseAnd(exploredMask, notWall, exploredMask);
using var notPlayer = new Mat();
Cv2.BitwiseNot(playerMask, notPlayer);
Cv2.BitwiseAnd(exploredMask, notPlayer, exploredMask);
return exploredMask;
}
private static void FilterSmallComponents(Mat mask, int minArea)
{
if (minArea <= 0) return;
@ -172,31 +151,21 @@ public class MinimapCapture : IDisposable
var size = classified.Size();
using var wallCount = new Mat(size, MatType.CV_8UC1, Scalar.Black);
using var exploredCount = new Mat(size, MatType.CV_8UC1, Scalar.Black);
foreach (var frame in _frameBuffer)
{
using var isWall = new Mat();
Cv2.Compare(frame, new Scalar((byte)MapCell.Wall), isWall, CmpType.EQ);
Cv2.Add(wallCount, new Scalar(1), wallCount, isWall);
using var isExplored = new Mat();
Cv2.Compare(frame, new Scalar((byte)MapCell.Explored), isExplored, CmpType.EQ);
Cv2.Add(exploredCount, new Scalar(1), exploredCount, isExplored);
}
// Apply vote thresholds
// Apply vote threshold
using var wallPass = new Mat();
Cv2.Threshold(wallCount, wallPass,
_config.WallTemporalThreshold - 0.5, 255, ThresholdTypes.Binary);
using var exploredPass = new Mat();
Cv2.Threshold(exploredCount, exploredPass,
_config.ExploredTemporalThreshold - 0.5, 255, ThresholdTypes.Binary);
// Build smoothed result (explored wins over wall)
var result = new Mat(size, MatType.CV_8UC1, Scalar.Black);
result.SetTo(new Scalar((byte)MapCell.Wall), wallPass);
result.SetTo(new Scalar((byte)MapCell.Explored), exploredPass);
return result;
}
@ -236,12 +205,8 @@ public class MinimapCapture : IDisposable
using var wallMask = BuildWallMask(satChan, valueChan, playerMask);
if (stage == MinimapDebugStage.Walls) return EncodePng(wallMask);
using var exploredMask = BuildExploredMask(valueChan, wallMask, playerMask);
if (stage == MinimapDebugStage.Explored) return EncodePng(exploredMask);
// Classified
// Classified (walls + player only — explored is tracked by WorldMap)
using var classified = new Mat(_config.CaptureSize, _config.CaptureSize, MatType.CV_8UC3, Scalar.Black);
classified.SetTo(new Scalar(104, 64, 31), exploredMask);
classified.SetTo(new Scalar(26, 45, 61), wallMask);
classified.SetTo(new Scalar(0, 165, 255), playerMask);
return EncodePng(classified);
@ -275,25 +240,22 @@ public class MinimapCapture : IDisposable
Cv2.InRange(hsv, _config.PlayerLoHSV, _config.PlayerHiHSV, playerMask);
using var wallMask = BuildWallMask(satChan, valueChan, playerMask);
using var exploredMask = BuildExploredMask(valueChan, wallMask, playerMask);
// Colorized classified
// Colorized classified (walls + player)
using var classified = new Mat(_config.CaptureSize, _config.CaptureSize, MatType.CV_8UC3, Scalar.Black);
classified.SetTo(new Scalar(104, 64, 31), exploredMask); // blue
classified.SetTo(new Scalar(26, 45, 61), wallMask); // brown
classified.SetTo(new Scalar(0, 165, 255), playerMask); // orange
Cv2.ImWrite(Path.Combine(dir, "01-raw.png"), bgr);
Cv2.ImWrite(Path.Combine(dir, "02-walls.png"), wallMask);
Cv2.ImWrite(Path.Combine(dir, "03-explored.png"), exploredMask);
Cv2.ImWrite(Path.Combine(dir, "04-player.png"), playerMask);
Cv2.ImWrite(Path.Combine(dir, "05-classified.png"), classified);
Cv2.ImWrite(Path.Combine(dir, "03-player.png"), playerMask);
Cv2.ImWrite(Path.Combine(dir, "04-classified.png"), classified);
// HSV channels
var channels = Cv2.Split(hsv);
Cv2.ImWrite(Path.Combine(dir, "06-hue.png"), channels[0]);
Cv2.ImWrite(Path.Combine(dir, "07-sat.png"), channels[1]);
Cv2.ImWrite(Path.Combine(dir, "08-val.png"), channels[2]);
Cv2.ImWrite(Path.Combine(dir, "05-hue.png"), channels[0]);
Cv2.ImWrite(Path.Combine(dir, "06-sat.png"), channels[1]);
Cv2.ImWrite(Path.Combine(dir, "07-val.png"), channels[2]);
foreach (var c in channels) c.Dispose();
Log.Information("Debug minimap images saved to {Dir}", Path.GetFullPath(dir));