poe2-bot/tools/OcrDaemon/TemplateMatchHandler.cs
2026-02-12 01:04:19 -05:00

60 lines
2.1 KiB
C#

namespace OcrDaemon;
using System.Drawing;
using System.Drawing.Imaging;
using OpenCvSharp;
using OpenCvSharp.Extensions;
class TemplateMatchHandler
{
public object HandleTemplateMatch(Request req)
{
if (string.IsNullOrEmpty(req.Path))
return new ErrorResponse("match-template command requires 'path' (template image file)");
if (!System.IO.File.Exists(req.Path))
return new ErrorResponse($"Template file not found: {req.Path}");
using var screenshot = ScreenCapture.CaptureOrLoad(req.File, req.Region);
using var screenMat = BitmapConverter.ToMat(screenshot);
using var template = Cv2.ImRead(req.Path, ImreadModes.Color);
if (template.Empty())
return new ErrorResponse($"Failed to load template image: {req.Path}");
// Convert screenshot from BGRA to BGR if needed
using var screenBgr = new Mat();
if (screenMat.Channels() == 4)
Cv2.CvtColor(screenMat, screenBgr, ColorConversionCodes.BGRA2BGR);
else
screenMat.CopyTo(screenBgr);
// Template must fit within screenshot
if (template.Rows > screenBgr.Rows || template.Cols > screenBgr.Cols)
return new TemplateMatchResponse { Found = false };
using var result = new Mat();
Cv2.MatchTemplate(screenBgr, template, result, TemplateMatchModes.CCoeffNormed);
Cv2.MinMaxLoc(result, out _, out double maxVal, out _, out OpenCvSharp.Point maxLoc);
double threshold = req.Threshold > 0 ? req.Threshold / 100.0 : 0.7;
if (maxVal < threshold)
return new TemplateMatchResponse { Found = false, Confidence = maxVal };
// Calculate center coordinates — offset by region origin if provided
int offsetX = req.Region?.X ?? 0;
int offsetY = req.Region?.Y ?? 0;
return new TemplateMatchResponse
{
Found = true,
X = offsetX + maxLoc.X + template.Cols / 2,
Y = offsetY + maxLoc.Y + template.Rows / 2,
Width = template.Cols,
Height = template.Rows,
Confidence = maxVal,
};
}
}