work no minimap
This commit is contained in:
parent
3087f9146e
commit
7d10f1d2a9
4 changed files with 70 additions and 5 deletions
|
|
@ -205,8 +205,9 @@ public class MinimapCapture : IFrameConsumer, IDisposable
|
|||
|
||||
private Mat BuildWallMask(Mat hsv, Mat playerMask, bool sample = false)
|
||||
{
|
||||
var lo = _colorTracker.AdaptedLo ?? _config.WallLoHSV;
|
||||
var hi = _colorTracker.AdaptedHi ?? _config.WallHiHSV;
|
||||
var isCorner = _detectedMode == MinimapMode.Corner;
|
||||
var lo = isCorner ? _config.CornerWallLoHSV : (_colorTracker.AdaptedLo ?? _config.WallLoHSV);
|
||||
var hi = isCorner ? _config.CornerWallHiHSV : (_colorTracker.AdaptedHi ?? _config.WallHiHSV);
|
||||
|
||||
var wallMask = new Mat();
|
||||
Cv2.InRange(hsv, lo, hi, wallMask);
|
||||
|
|
@ -215,7 +216,7 @@ public class MinimapCapture : IFrameConsumer, IDisposable
|
|||
Cv2.BitwiseNot(playerMask, notPlayer);
|
||||
Cv2.BitwiseAnd(wallMask, notPlayer, wallMask);
|
||||
|
||||
if (sample)
|
||||
if (sample && !isCorner)
|
||||
_colorTracker.SampleFrame(hsv, wallMask);
|
||||
|
||||
using var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(3, 3));
|
||||
|
|
|
|||
|
|
@ -98,11 +98,15 @@ public class MinimapConfig
|
|||
public Scalar PlayerLoHSV { get; set; } = new(5, 80, 80);
|
||||
public Scalar PlayerHiHSV { get; set; } = new(25, 255, 255);
|
||||
|
||||
// Wall detection: target #A2AEE5 (blue-lavender structure lines)
|
||||
// Wall detection (overlay): target #A2AEE5 (blue-lavender structure lines)
|
||||
// HSV(115, 75, 229) — blue hue, low-medium saturation, bright
|
||||
public Scalar WallLoHSV { get; set; } = new(110, 25, 190);
|
||||
public Scalar WallHiHSV { get; set; } = new(136, 120, 255);
|
||||
|
||||
// Wall detection (corner): wider V range for faded walls
|
||||
public Scalar CornerWallLoHSV { get; set; } = new(110, 25, 100);
|
||||
public Scalar CornerWallHiHSV { get; set; } = new(136, 120, 255);
|
||||
|
||||
// Connected components: minimum area to keep (kills speckle)
|
||||
public int WallMinArea { get; set; } = 30;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,11 +3,24 @@ using Serilog;
|
|||
|
||||
namespace Poe2Trade.Navigation;
|
||||
|
||||
/// <summary>
|
||||
/// Last BFS result for visualization.
|
||||
/// </summary>
|
||||
internal record BfsResult(
|
||||
List<Point> BestFrontier, // frontier cells in the chosen direction (canvas coords)
|
||||
List<Point> OtherFrontier, // frontier cells in other directions (canvas coords)
|
||||
double DirX, double DirY, // chosen direction (unit vector)
|
||||
int PlayerCx, int PlayerCy // player position on canvas
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// BFS pathfinding through the world map canvas. Pure function — reads canvas, never modifies it.
|
||||
/// </summary>
|
||||
internal class PathFinder
|
||||
{
|
||||
/// <summary>Last BFS result for viewport overlay.</summary>
|
||||
public BfsResult? LastResult { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// BFS through walkable (Explored) cells to find the best frontier direction.
|
||||
/// Instead of stopping at the nearest frontier, runs the full BFS and counts
|
||||
|
|
@ -40,9 +53,10 @@ internal class PathFinder
|
|||
ReadOnlySpan<int> dxs = [-1, 0, 1, -1, 1, -1, 0, 1];
|
||||
ReadOnlySpan<int> dys = [-1, -1, -1, 0, 0, 1, 1, 1];
|
||||
|
||||
// Count frontier cells per first-step direction
|
||||
// Count frontier cells per first-step direction, and collect positions
|
||||
var frontierCounts = new Dictionary<int, int>();
|
||||
var firstStepCoords = new Dictionary<int, (short gx, short gy)>();
|
||||
var frontierByKey = new Dictionary<int, List<Point>>();
|
||||
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
|
|
@ -71,7 +85,9 @@ internal class PathFinder
|
|||
{
|
||||
frontierCounts[fsKey] = 1;
|
||||
firstStepCoords[fsKey] = (firstStepX[cellIdx], firstStepY[cellIdx]);
|
||||
frontierByKey[fsKey] = [];
|
||||
}
|
||||
frontierByKey[fsKey].Add(new Point(wx, wy));
|
||||
break; // don't double-count this cell
|
||||
}
|
||||
}
|
||||
|
|
@ -114,6 +130,7 @@ internal class PathFinder
|
|||
if (frontierCounts.Count == 0)
|
||||
{
|
||||
Log.Information("BFS: no reachable frontier within {Radius}px", searchRadius);
|
||||
LastResult = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -138,6 +155,16 @@ internal class PathFinder
|
|||
dirX /= len;
|
||||
dirY /= len;
|
||||
|
||||
// Store result for visualization
|
||||
var bestFrontier = frontierByKey[bestKey];
|
||||
var otherFrontier = new List<Point>();
|
||||
foreach (var (key, pts) in frontierByKey)
|
||||
{
|
||||
if (key != bestKey)
|
||||
otherFrontier.AddRange(pts);
|
||||
}
|
||||
LastResult = new BfsResult(bestFrontier, otherFrontier, dirX, dirY, cx, cy);
|
||||
|
||||
Log.Debug("BFS: {DirCount} directions, best={Best} frontier cells, dir=({Dx:F2},{Dy:F2})",
|
||||
frontierCounts.Count, bestCount, dirX, dirY);
|
||||
return (dirX, dirY);
|
||||
|
|
|
|||
|
|
@ -459,6 +459,39 @@ public class WorldMap : IDisposable
|
|||
colored.Set(r, c, new Vec3b(55, 40, 28));
|
||||
}
|
||||
|
||||
// BFS overlay: frontier cells + direction line
|
||||
var bfs = _pathFinder.LastResult;
|
||||
if (bfs != null)
|
||||
{
|
||||
// Other frontier directions (dim cyan)
|
||||
foreach (var pt in bfs.OtherFrontier)
|
||||
{
|
||||
var vx = pt.X - x0;
|
||||
var vy = pt.Y - y0;
|
||||
if (vx >= 0 && vx < viewSize && vy >= 0 && vy < viewSize)
|
||||
colored.Set(vy, vx, new Vec3b(100, 80, 0));
|
||||
}
|
||||
|
||||
// Best frontier direction (bright green)
|
||||
foreach (var pt in bfs.BestFrontier)
|
||||
{
|
||||
var vx = pt.X - x0;
|
||||
var vy = pt.Y - y0;
|
||||
if (vx >= 0 && vx < viewSize && vy >= 0 && vy < viewSize)
|
||||
colored.Set(vy, vx, new Vec3b(0, 220, 0));
|
||||
}
|
||||
|
||||
// Direction line from player
|
||||
var px2 = bfs.PlayerCx - x0;
|
||||
var py2 = bfs.PlayerCy - y0;
|
||||
var lineLen = 60;
|
||||
var ex = (int)(px2 + bfs.DirX * lineLen);
|
||||
var ey = (int)(py2 + bfs.DirY * lineLen);
|
||||
Cv2.ArrowedLine(colored, new Point(px2, py2), new Point(ex, ey),
|
||||
new Scalar(0, 220, 0), 2, tipLength: 0.3);
|
||||
}
|
||||
|
||||
// Player dot (orange, on top)
|
||||
var px = cx - x0;
|
||||
var py = cy - y0;
|
||||
if (px >= 0 && px < viewSize && py >= 0 && py < viewSize)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue