first commit
This commit is contained in:
commit
761b95080f
404 files changed
+312608
No files matched your search
@@ -0,0 +1,75 @@
|
||||
using OpenCvSharp;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace anjianjingling.Vision
|
||||
{
|
||||
/// <summary>
|
||||
/// 找图:OpenCV 模板匹配(TM_CCOEFF_NORMED),支持相似度阈值。
|
||||
/// </summary>
|
||||
public sealed class ImageFinder : IDisposable
|
||||
{
|
||||
private readonly Dictionary<string, Mat> _templateCache = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
private static Mat BitmapToMat(Bitmap bmp)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
bmp.Save(ms, ImageFormat.Png);
|
||||
return Cv2.ImDecode(ms.ToArray(), ImreadModes.Color);
|
||||
}
|
||||
|
||||
private Mat LoadTemplate(string path)
|
||||
{
|
||||
if (_templateCache.TryGetValue(path, out var cached)) return cached;
|
||||
if (!File.Exists(path))
|
||||
throw new FileNotFoundException($"模板图片不存在:{path}");
|
||||
var mat = Cv2.ImRead(path, ImreadModes.Color);
|
||||
if (mat.Empty())
|
||||
throw new InvalidDataException($"模板图片无法读取:{path}");
|
||||
_templateCache[path] = mat;
|
||||
return mat;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 在 haystack 位图中查找模板。
|
||||
/// </summary>
|
||||
/// <param name="haystack">被查找的画面(通常是区域截图)</param>
|
||||
/// <param name="templatePath">模板图路径</param>
|
||||
/// <param name="threshold">相似度阈值 0~1</param>
|
||||
/// <param name="offsetX">结果坐标要加上的屏幕偏移 X</param>
|
||||
/// <param name="offsetY">结果坐标要加上的屏幕偏移 Y</param>
|
||||
/// <returns>匹配中心屏幕坐标与相似度;未达阈值返回 (-1,-1,score)</returns>
|
||||
public (int X, int Y, double Score) Find(Bitmap haystack, string templatePath,
|
||||
double threshold, int offsetX = 0, int offsetY = 0)
|
||||
{
|
||||
using var hay = BitmapToMat(haystack);
|
||||
using var tpl = LoadTemplate(templatePath);
|
||||
|
||||
if (tpl.Width > hay.Width || tpl.Height > hay.Height)
|
||||
throw new ArgumentException($"模板图({tpl.Width}x{tpl.Height})大于查找区域({hay.Width}x{hay.Height})");
|
||||
|
||||
using var result = new Mat();
|
||||
Cv2.MatchTemplate(hay, tpl, result, TemplateMatchModes.CCoeffNormed);
|
||||
Cv2.MinMaxLoc(result, out _, out double maxVal, out _, out OpenCvSharp.Point maxLoc);
|
||||
|
||||
if (maxVal >= threshold)
|
||||
{
|
||||
int cx = offsetX + maxLoc.X + tpl.Width / 2;
|
||||
int cy = offsetY + maxLoc.Y + tpl.Height / 2;
|
||||
return (cx, cy, maxVal);
|
||||
}
|
||||
return (-1, -1, maxVal);
|
||||
}
|
||||
|
||||
/// <summary>清除模板缓存(模板文件更新后调用)。</summary>
|
||||
public void ClearCache()
|
||||
{
|
||||
foreach (var m in _templateCache.Values) m.Dispose();
|
||||
_templateCache.Clear();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ClearCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user